<commit_before>'use strict';

/* Controllers */

angular.module('raw.controllers', [])

  .controller('RawCtrl', function ($scope, dataService, $http, $timeout, $sce) {

    $scope.loading = false;

    // Clipboard
    $scope.$watch('clipboardText', function (text) {
      if (!text) return;

      $scope.loading = true;

      if (is.url(text)) {
        $scope.importMode = 'url';
        $timeout(function() { $scope.url = text; });
        return;
      }

      try {
        var json = JSON.parse(text);
        selectArray(json);
        $scope.loading = false;
      }
      catch(error) {
        parseText(text);
      }

    });

    $scope.antani = function(d){
      $scope.loading = true;
      var json = dataService.flatJSON(d);
      parseText(d3.tsv.format(json))
    }

    // select Array in JSON
    function selectArray(json){
      $scope.json = json;
      $scope.structure = [];
      expand(json);
    }

    // parse Text
    function parseText(text){
    //  $scope.loading = false;
      $scope.json = null;
      $scope.text = text;
      $scope.parse(text);
    }

    // load File
    $scope.uploadFile = function (file) {

      if (file.size) {

        $scope.loading = true;

        // excel
        if (file.name.search(/\.xls|\.xlsx/) != -1 || file.type.search('sheet') != -1) {
          dataService.loadExcel(file)
          .then(function(worksheets){
            $scope.fileName = file.name;
            $scope.loading = false;
            // multiple sheets
            if (worksheets.length > 1) {
              $scope.worksheets = worksheets;
            // single > parse
            } else {
              $scope.parse(worksheets[0].text);
            }
          })
        }

        // json
        if (file.type.search('json') != -1) {
          dataService.loadJson(file)
          .then(function(json){
            $scope.fileName = file.name;
            selectArray(json);
          })
        }

        // txt
        if (file.type.search('text') != -1) {
          dataService.loadText(file)
          .then(function(text){
            $scope.fileName = file.name;
            parseText(text);
          })
        }
      }
    };

    function parseData(json){

      $scope.loading = false;
    //  $scope.parsed = true;

      if (!json) return;
      try {
        selectArray(json);
      }
      catch(error) {
        console.log(error)
        parseText(json);
      }

    }

    // load URl
    $scope.$watch('url', function (url) {

      if(!url || !url.length) {
        return;
      }

      if (is.not.url(url)) {
        $scope.error = "Please insert a valid URL";
        return;
      }

      $scope.loading = true;
      var error = null;
      // first trying jsonp
      $http.jsonp($sce.trustAsResourceUrl(url), {jsonpCallbackParam: 'callback'})
          .then(function(response) {
            $scope.fileName = url;
            parseData(response.data);
      }, function(response) {

          $http.get($sce.trustAsResourceUrl(url), {responseType:'arraybuffer'})
          .then(function(response) {

            var data = new Uint8Array(response.data);
            var arr = new Array();
            for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
            var bstr = arr.join("");

            try {
              var workbook = XLS.read(bstr, {type:"binary"});
              var worksheets = [];
        			var sheet_name_list = workbook.SheetNames;

        			sheet_name_list.forEach(function(y) {
        			  var worksheet = workbook.Sheets[y];
        				worksheets.push({
        					name: y,
        					text : XLSX.utils.sheet_to_csv(worksheet),
                  rows: worksheet['!range'].e.r
        				})
        			});

              $scope.fileName = url;
              $scope.loading = false;

              // multiple sheets
              if (worksheets.length > 1) {
                $scope.worksheets = worksheets;
              // single > parse
              } else {
                parseText(worksheets[0].text);
              }
            }
            catch(error) {
              $scope.fileName = url;
              try {
                var json = JSON.parse(bstr);
                selectArray(json);
              }
              catch(error) {
                parseText(bstr);
              }
            }

          },
          function(response){
            $scope.loading = false;
            $scope.error = "Something wrong with the URL you provided. Please be sure it is the correct address.";
          }
        )

      });

    });

    $scope.samples = [
      { title : 'Biggest cities per continent', type : 'Distributions', url : 'data/cities.csv'},
      { title : 'Countries GDP', type : 'Other', url : 'data/countriesGDP.csv'},
      { title : 'Cars', type : 'Multivariate', url : 'data/multivariate.csv' },
      { title : 'Movies', type : 'Dispersions', url : 'data/dispersions.csv' },
      { title : 'Music industry', type: 'Time Series', url : 'data/music.csv' },
      { title : 'Lineup', type : 'Time chunks', url : 'data/lineup.tsv' },
      { title : 'Orchestras', type : 'Hierarchies (weighted)', url : 'data/orchestra.csv' },
      { title : 'Animal kingdom', type: 'Hierarchies', url : 'data/animals.tsv' },
      { title : 'Titanic\'s passengers', type : 'Multi categorical', url : 'data/titanic.tsv' },
      { title : 'Most frequent letters', type: 'Matrix (narrow)', url:'data/letters.tsv'}
    ]

    $scope.selectSample = function(sample) {
//    $scope.$watch('sample', function (sample){
      if (!sample) return;
      $scope.text = "";
      $scope.loading = true;
      dataService.loadSample(sample.url).then(
        function(data){
          $scope.text = data.replace(/\r/g, '');
          $scope.loading = false;
        },
        function(error){
          $scope.error = error;
          $scope.loading = false;
        }
      );
    }//);

    $(document.getElementById("load-data")).on('dragenter', function(e){
      $scope.importMode = 'file';
      $scope.parsed = false;
      $scope.$digest();
    });

    $scope.$watch('dataView', function (n,o){
      if (!$('.parsed .CodeMirror')[0]) return;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      $timeout(function() { cm.refresh() });
    });

    // init
    $scope.raw = raw;
    $scope.data = [];
    $scope.metadata = [];
    $scope.error = false;
  //  $scope.loading = true;

    $scope.importMode = 'clipboard';

    $scope.categories = ['Hierarchies', 'Time Series', 'Distributions', 'Correlations', 'Others'];

    $scope.bgColors = {
      'Hierarchies': '#0f0',
      'Time Series': 'rgb(255, 185, 5)',
      'Distributions': 'rgb(5, 205, 255)',
      'Correlations': '#df0',
      'Others': '#0f0'
    }

    $scope.$watch('files', function () {
      $scope.uploadFile($scope.files);
    });

    $scope.log = '';

    $scope.files=[];

    $scope.$watch('importMode', function(){
      // reset
      $scope.parsed = false;
      $scope.loading = false;
      $scope.clipboardText = "";
      $scope.unstacked = false;
      $scope.text = "";
      $scope.data = [];
      $scope.json = null;
      $scope.worksheets = [];
      $scope.fileName = null;
      $scope.url = "";
      //$scope.$apply();
    })

    var arrays = [];

    $scope.unstack = function(){
      if (!$scope.stackDimension) return;
      var data = $scope.data;
      var base = $scope.stackDimension.key;

      var unstacked = [];

      data.forEach(function(row){
        for (var column in row) {
            if (column == base) continue;
            var obj = {};
            obj[base] = row[base];
            obj.column = column;
            obj.value = row[column];
            unstacked.push(obj);
          }
      })
      $scope.oldData = data;
      parseText(d3.tsv.format(unstacked));

      $scope.unstacked = true;

    }

    $scope.stack = function(){
      parseText(d3.tsv.format($scope.oldData));
      $scope.unstacked = false;
    }

    function jsonTree(json){
      // mettere try
      var tree = JSON.parse(json);
      $scope.json = tree;
      $scope.structure = [];
      //console.log(JSON.parse(json));
      expand(tree);
    }

    function expand(parent){
      for (var child in parent) {
        if (is.object(parent[child]) || is.array(parent[child])) {
          expand(parent[child]);
          if (is.array(parent[child])) arrays.push(child);
        }
      }
      //console.log(child,parent[child])
    }

    // very improbable function to determine if pivot table or not.
    // pivotable index
    // calculate if values repeat themselves
    // calculate if values usually appear in more columns

    function pivotable(array) {

      var n = array.length;
      var rows = {};

      array.forEach(function(o){
        for (var p in o) {
          if (!rows.hasOwnProperty(p)) rows[p] = {};
          if (!rows[p].hasOwnProperty(o[p])) rows[p][o[p]] = -1;
          rows[p][o[p]]+=1;
        }
      })

      for (var r in rows) {
        for (var p in rows[r]) {
          for (var ra in rows) {
            if (r == ra) break;
        //    if (p == "") break;
            if (rows[ra].hasOwnProperty(p)) rows[r][p]-=2.5;

          }
        }
      }

      var m = d3.values(rows).map(d3.values).map(function(d){ return d3.sum(d)/n; });
      //console.log(d3.mean(m),m)
      $scope.pivot = d3.mean(m);

    }

    $scope.parse = function(text){

      if ($scope.model) $scope.model.clear();

      $scope.text = text;
      $scope.data = [];
      $scope.metadata = [];
      $scope.error = false;
      //$scope.importMode = null;
      //$scope.$apply();

      if (!text) return;

      try {
        var parser = raw.parser();
        $scope.data = parser(text);
        $scope.metadata = parser.metadata(text);
        $scope.error = false;
        pivotable($scope.data);
        $scope.parsed = true;

        $timeout(function() {
          $scope.charts = raw.charts.values().sort(function (a,b){ return d3.ascending(a.category(),b.category()) || d3.ascending(a.title(),b.title()) })
          $scope.chart = $scope.charts.filter(function(d){return d.title() == 'Scatter Plot'})[0];
          $scope.model = $scope.chart ? $scope.chart.model() : null;
        }, 10);
      } catch(e){
        $scope.data = [];
        $scope.metadata = [];
        $scope.error = e.name == "ParseError" ? +e.message : false;
      }
      if (!$scope.data.length && $scope.model) $scope.model.clear();
      $scope.loading = false;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      $timeout(function() { cm.refresh(); cm.refresh(); } );
    }

    $scope.delayParse = dataService.debounce($scope.parse, 500, false);

    $scope.$watch("text", function (text){
      if (!text) return;
      $scope.loading = true;
      $scope.delayParse(text);
    });

    $scope.$watch('error', function (error){
      if (!$('.parsed .CodeMirror')[0]) return;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      if (!error) {
        cm.removeLineClass($scope.lastError,'wrap','line-error');
        return;
      }
      cm.addLineClass(error, 'wrap', 'line-error');
      cm.scrollIntoView(error);
      $scope.lastError = error;
    })

    $('body').mousedown(function (e,ui){
      if ($(e.target).hasClass("dimension-info-toggle")) return;
      $('.dimensions-wrapper').each(function (e){
        angular.element(this).scope().open = false;
        angular.element(this).scope().$apply();
      })
    })

    $scope.codeMirrorOptions = {
      dragDrop : false,
      lineNumbers : true,
      lineWrapping : true
    }

    $scope.selectChart = function(chart){
      if (chart == $scope.chart) return;
      $scope.model.clear();
      $scope.chart = chart;
      $scope.model = $scope.chart.model();
      chart.option.value = $('.col-lg-9').width();

    }

    function refreshScroll(){
      $('[data-spy="scroll"]').each(function () {
        $(this).scrollspy('refresh');
      });
    }

    $(window).scroll(function(){

      // check for mobile
      if ($(window).width() < 760 || $('#mapping').height() < 300) return;

      var scrollTop = $(window).scrollTop() + 0,
          mappingTop = $('#mapping').offset().top + 10,
          mappingHeight = $('#mapping').height(),
          isBetween = scrollTop > mappingTop + 50 && scrollTop <= mappingTop + mappingHeight - $(".sticky").height() - 20,
          isOver = scrollTop > mappingTop + mappingHeight - $(".sticky").height() - 20,
          mappingWidth = mappingWidth ? mappingWidth : $('.mapping').width();

      if (mappingHeight-$('.dimensions-list').height() > 90) return;
      //console.log(mappingHeight-$('.dimensions-list').height())
      if (isBetween) {
        $(".sticky")
          .css("position","fixed")
          .css("width", mappingWidth+"px")
          .css("top","20px")
      }

     if(isOver) {
        $(".sticky")
          .css("position","fixed")
          .css("width", mappingWidth+"px")
          .css("top", (mappingHeight - $(".sticky").height() + 0 - scrollTop+mappingTop) + "px");
          return;
      }

      if (isBetween) return;

      $(".sticky")
        .css("position","relative")
        .css("top","")
        .css("width", "");

    })

      $scope.sortCategory = function (chart) {
        // sort first by category, then by title
        return [chart.category(),chart.title()];
      };

    $(document).ready(refreshScroll);

  })
<commit_msg>fix: minor fix<commit_after>'use strict';

/* Controllers */

angular.module('raw.controllers', [])

  .controller('RawCtrl', function ($scope, dataService, $http, $timeout, $sce) {

    $scope.loading = false;

    // Clipboard
    $scope.$watch('clipboardText', function (text) {
      if (!text) return;

      $scope.loading = true;

      if (is.url(text)) {
        $scope.importMode = 'url';
        $timeout(function() { $scope.url = text; });
        return;
      }

      try {
        var json = JSON.parse(text);
        selectArray(json);
        $scope.loading = false;
      }
      catch(error) {
        parseText(text);
      }

    });

    $scope.antani = function(d){
      $scope.loading = true;
      var json = dataService.flatJSON(d);
      parseText(d3.tsv.format(json))
    }

    // select Array in JSON
    function selectArray(json){
      $scope.json = json;
      $scope.structure = [];
      expand(json);
    }

    // parse Text
    function parseText(text){
    //  $scope.loading = false;
      $scope.json = null;
      $scope.text = text;
      $scope.parse(text);
    }

    // load File
    $scope.uploadFile = function (file) {

      if (file.size) {

        $scope.loading = true;

        // excel
        if (file.name.search(/\.xls|\.xlsx/) != -1 || file.type.search('sheet') != -1) {
          dataService.loadExcel(file)
          .then(function(worksheets){
            $scope.fileName = file.name;
            $scope.loading = false;
            // multiple sheets
            if (worksheets.length > 1) {
              $scope.worksheets = worksheets;
            // single > parse
            } else {
              $scope.parse(worksheets[0].text);
            }
          })
        }

        // json
        if (file.type.search('json') != -1) {
          dataService.loadJson(file)
          .then(function(json){
            $scope.fileName = file.name;
            selectArray(json);
          })
        }

        // txt
        if (file.type.search('text') != -1) {
          dataService.loadText(file)
          .then(function(text){
            $scope.fileName = file.name;
            parseText(text);
          })
        }
      }
    };

    function parseData(json){

      $scope.loading = false;
    //  $scope.parsed = true;

      if (!json) return;
      try {
        selectArray(json);
      }
      catch(error) {
        console.log(error)
        parseText(json);
      }

    }

    // load URl
    $scope.$watch('url', function (url) {

      if(!url || !url.length) {
        return;
      }

      if (is.not.url(url)) {
        $scope.error = "Please insert a valid URL";
        return;
      }

      $scope.loading = true;
      var error = null;
      // first trying jsonp
      $http.jsonp($sce.trustAsResourceUrl(url), {jsonpCallbackParam: 'callback'})
          .then(function(response) {
            $scope.fileName = url;
            parseData(response.data);
      }, function(response) {

          $http.get($sce.trustAsResourceUrl(url), {responseType:'arraybuffer'})
          .then(function(response) {

            var data = new Uint8Array(response.data);
            var arr = new Array();
            for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
            var bstr = arr.join("");

            try {
              var workbook = XLS.read(bstr, {type:"binary"});
              var worksheets = [];
        			var sheet_name_list = workbook.SheetNames;

        			sheet_name_list.forEach(function(y) {
        			  var worksheet = workbook.Sheets[y];
        				worksheets.push({
        					name: y,
        					text : XLSX.utils.sheet_to_csv(worksheet),
                  rows: worksheet['!range'].e.r
        				})
        			});

              $scope.fileName = url;
              $scope.loading = false;

              // multiple sheets
              if (worksheets.length > 1) {
                $scope.worksheets = worksheets;
              // single > parse
              } else {
                parseText(worksheets[0].text);
              }
            }
            catch(error) {
              $scope.fileName = url;
              try {
                var json = JSON.parse(bstr);
                selectArray(json);
              }
              catch(error) {
                parseText(bstr);
              }
            }

          },
          function(response){
            $scope.loading = false;
            $scope.error = "Something wrong with the URL you provided. Please be sure it is the correct address.";
          }
        )

      });

    });

    $scope.samples = [
      { title : 'Biggest cities per continent', type : 'Distributions', url : 'data/cities.csv'},
      { title : 'Countries GDP', type : 'Other', url : 'data/countriesGDP.csv'},
      { title : 'Cars', type : 'Multivariate', url : 'data/multivariate.csv' },
      { title : 'Movies', type : 'Dispersions', url : 'data/dispersions.csv' },
      { title : 'Music industry', type: 'Time Series', url : 'data/music.csv' },
      { title : 'Lineup', type : 'Time chunks', url : 'data/lineup.tsv' },
      { title : 'Orchestras', type : 'Hierarchies (weighted)', url : 'data/orchestra.csv' },
      { title : 'Animal kingdom', type: 'Hierarchies', url : 'data/animals.tsv' },
      { title : 'Titanic\'s passengers', type : 'Multi categorical', url : 'data/titanic.tsv' },
      { title : 'Most frequent letters', type: 'Matrix (narrow)', url:'data/letters.tsv'}
    ]

    $scope.selectSample = function(sample) {
//    $scope.$watch('sample', function (sample){
      if (!sample) return;
      $scope.text = "";
      $scope.loading = true;
      dataService.loadSample(sample.url).then(
        function(data){
          $scope.text = data.replace(/\r/g, '');
          $scope.loading = false;
        },
        function(error){
          $scope.error = error;
          $scope.loading = false;
        }
      );
    }//);

    $(document.getElementById("load-data")).on('dragenter', function(e){
      $scope.importMode = 'file';
      $scope.parsed = false;
      $scope.$digest();
    });

    $scope.$watch('dataView', function (n,o){
      if (!$('.parsed .CodeMirror')[0]) return;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      $timeout(function() { cm.refresh() });
    });

    // init
    $scope.raw = raw;
    $scope.data = [];
    $scope.metadata = [];
    $scope.error = false;
  //  $scope.loading = true;

    $scope.importMode = 'clipboard';

    $scope.categories = ['Hierarchies', 'Time Series', 'Distributions', 'Correlations', 'Others'];

    $scope.bgColors = {
      'Hierarchies': '#0f0',
      'Time Series': 'rgb(255, 185, 5)',
      'Distributions': 'rgb(5, 205, 255)',
      'Correlations': '#df0',
      'Others': '#0f0'
    }

    $scope.$watch('files', function () {
      $scope.uploadFile($scope.files);
    });

    $scope.log = '';

    $scope.files=[];

    $scope.$watch('importMode', function(){
      // reset
      $scope.parsed = false;
      $scope.loading = false;
      $scope.clipboardText = "";
      $scope.unstacked = false;
      $scope.text = "";
      $scope.data = [];
      $scope.json = null;
      $scope.worksheets = [];
      $scope.fileName = null;
      $scope.url = "";
      //$scope.$apply();
    })

    var arrays = [];

    $scope.unstack = function(){
      if (!$scope.stackDimension) return;
      var data = $scope.data;
      var base = $scope.stackDimension.key;

      var unstacked = [];

      data.forEach(function(row){
        for (var column in row) {
            if (column == base) continue;
            var obj = {};
            obj[base] = row[base];
            obj.column = column;
            obj.value = row[column];
            unstacked.push(obj);
          }
      })
      $scope.oldData = data;
      parseText(d3.tsv.format(unstacked));

      $scope.unstacked = true;

    }

    $scope.stack = function(){
      parseText(d3.tsv.format($scope.oldData));
      $scope.unstacked = false;
    }

    function jsonTree(json){
      // mettere try
      var tree = JSON.parse(json);
      $scope.json = tree;
      $scope.structure = [];
      //console.log(JSON.parse(json));
      expand(tree);
    }

    function expand(parent){
      for (var child in parent) {
        if (is.object(parent[child]) || is.array(parent[child])) {
          expand(parent[child]);
          if (is.array(parent[child])) arrays.push(child);
        }
      }
      //console.log(child,parent[child])
    }

    // very improbable function to determine if pivot table or not.
    // pivotable index
    // calculate if values repeat themselves
    // calculate if values usually appear in more columns

    function pivotable(array) {

      var n = array.length;
      var rows = {};

      array.forEach(function(o){
        for (var p in o) {
          if (!rows.hasOwnProperty(p)) rows[p] = {};
          if (!rows[p].hasOwnProperty(o[p])) rows[p][o[p]] = -1;
          rows[p][o[p]]+=1;
        }
      })

      for (var r in rows) {
        for (var p in rows[r]) {
          for (var ra in rows) {
            if (r == ra) break;
        //    if (p == "") break;
            if (rows[ra].hasOwnProperty(p)) rows[r][p]-=2.5;

          }
        }
      }

      var m = d3.values(rows).map(d3.values).map(function(d){ return d3.sum(d)/n; });
      //console.log(d3.mean(m),m)
      $scope.pivot = d3.mean(m);

    }

    $scope.parse = function(text){

      if ($scope.model) $scope.model.clear();

      $scope.text = text;
      $scope.data = [];
      $scope.metadata = [];
      $scope.error = false;
      //$scope.importMode = null;
      //$scope.$apply();

      if (!text) return;

      try {
        var parser = raw.parser();
        $scope.data = parser(text);
        $scope.metadata = parser.metadata(text);
        $scope.error = false;
        pivotable($scope.data);
        $scope.parsed = true;

        $timeout(function() {
          $scope.charts = raw.charts.values().sort(function (a,b){ return d3.ascending(a.category(),b.category()) || d3.ascending(a.title(),b.title()) })
          $scope.chart = $scope.charts.filter(function(d){return d.title() == 'Scatter Plot'})[0];
          $scope.model = $scope.chart ? $scope.chart.model() : null;
        }, 10);
      } catch(e){
        $scope.data = [];
        $scope.metadata = [];
        $scope.error = e.name == "ParseError" ? +e.message : false;
      }
      if (!$scope.data.length && $scope.model) $scope.model.clear();
      $scope.loading = false;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      $timeout(function() { cm.refresh(); cm.refresh(); } );
    }

    $scope.delayParse = dataService.debounce($scope.parse, 500, false);

    $scope.$watch("text", function (text){
      if (!text) return;
      $scope.loading = true;
      $scope.delayParse(text);
    });

    $scope.$watch('error', function (error){
      if (!$('.parsed .CodeMirror')[0]) return;
      var cm = $('.parsed .CodeMirror')[0].CodeMirror;
      if (!error) {
        cm.removeLineClass($scope.lastError,'wrap','line-error');
        return;
      }
      cm.addLineClass(error, 'wrap', 'line-error');
      cm.scrollIntoView(error);
      $scope.lastError = error;
    })

    $('body').mousedown(function (e,ui){
      if ($(e.target).hasClass("dimension-info-toggle")) return;
      $('.dimensions-wrapper').each(function (e){
        angular.element(this).scope().open = false;
        angular.element(this).scope().$apply();
      })
    })

    $scope.codeMirrorOptions = {
      dragDrop : false,
      lineNumbers : true,
      lineWrapping : true
    }

    $scope.selectChart = function(chart){
      if (chart == $scope.chart) return;
      $scope.model.clear();
      $scope.chart = chart;
      $scope.model = $scope.chart.model();
    }

    function refreshScroll(){
      $('[data-spy="scroll"]').each(function () {
        $(this).scrollspy('refresh');
      });
    }

    $(window).scroll(function(){

      // check for mobile
      if ($(window).width() < 760 || $('#mapping').height() < 300) return;

      var scrollTop = $(window).scrollTop() + 0,
          mappingTop = $('#mapping').offset().top + 10,
          mappingHeight = $('#mapping').height(),
          isBetween = scrollTop > mappingTop + 50 && scrollTop <= mappingTop + mappingHeight - $(".sticky").height() - 20,
          isOver = scrollTop > mappingTop + mappingHeight - $(".sticky").height() - 20,
          mappingWidth = mappingWidth ? mappingWidth : $('.mapping').width();

      if (mappingHeight-$('.dimensions-list').height() > 90) return;
      //console.log(mappingHeight-$('.dimensions-list').height())
      if (isBetween) {
        $(".sticky")
          .css("position","fixed")
          .css("width", mappingWidth+"px")
          .css("top","20px")
      }

     if(isOver) {
        $(".sticky")
          .css("position","fixed")
          .css("width", mappingWidth+"px")
          .css("top", (mappingHeight - $(".sticky").height() + 0 - scrollTop+mappingTop) + "px");
          return;
      }

      if (isBetween) return;

      $(".sticky")
        .css("position","relative")
        .css("top","")
        .css("width", "");

    })

      $scope.sortCategory = function (chart) {
        // sort first by category, then by title
        return [chart.category(),chart.title()];
      };

    $(document).ready(refreshScroll);

  })
<|endoftext|>


<commit_before>"use strict";
var squeezefox = angular.module('Squeezefox', ['ngAnimate'])
.config([
    '$compileProvider',
    function( $compileProvider )
    {
        $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|app):/);
    }
]);

squeezefox.controller('WindowCtrl', ['$scope', function ($scope) {

    $scope.players = [];
    $scope.selectedPlayer = {playerid: "",
                             name: ""};

                                //{playerid: "00:04:20:2b:39:ec", name: ''}; //XXX make dynamic
    $scope.current_window = "play";
    $scope.hidden = false;
    $scope.server = { addr: '', port: '', retries: 0 }
    localforage.getItem('server').then(function (cachedServer) {
        if (typeof cachedServer != 'undefined') {
            $scope.server = cachedServer;
        }
    });
    localforage.getItem('players').then(function (cachedPlayers) {
        $scope.players = cachedPlayers || [];
    })
    .then(function(){
        localforage.getItem('selectedPlayer', function(cachedSelectedPlayer) {
            /*
            * this is because the <select> tag will only remember the selection if ng-model is member of the array in ng-options (comparison by reference)
            * so we have to search the equal reference by eg playerid
            */
            for (var i = 0; i < $scope.players.length; i++) {
                if ($scope.players[i].playerid == cachedSelectedPlayer.playerid) {
                    $scope.selectedPlayer = $scope.players[i];
                    return;
                }
            }
        });
    });

    $scope.playlist = {current: 0, list: []};
    $scope.active   = false;
    $scope.power    = 0;
    $scope.playing  = false;
    $scope.shuffle  = 0;

    $scope.JSONRPC = function JSONRPC(payload, callback) {
        var xhr = new XMLHttpRequest({mozSystem: true});
        xhr.open("POST", "http://"+$scope.server.addr+':'+$scope.server.port+"/jsonrpc.js");
        xhr.responseType = "json";
        xhr.send(JSON.stringify(payload));
        xhr.onload = function() {
            localforage.setItem("server", $scope.server);
            localforage.setItem("selectedPlayer", $scope.selectedPlayer);
            $scope.active = true;
            // count retries for error handling? yagni?
            if ($scope.server.retries > 0) {
                $scope.server.retries = 0;
            }
            if (callback) { callback(this); }
        };
        xhr.onerror = function (e) {
            // XXX general error handling? provide another callback?
            $scope.server.retries++;
        };
    };

    /*
    * wrapper to JSONRPC. do a slim request on the current set playerid
    * params is a list, eg: ["play", ""]
    */
    $scope.queryPlayer = function (params, callback, playerid) {
        playerid = typeof playerid !== 'undefined' ? playerid : $scope.selectedPlayer.playerid;
        $scope.JSONRPC({"id":1,"method":"slim.request","params":[playerid, params]}, callback);
    }
    /*
    * do a query with empty playerid
    */
    $scope.queryServer = function (params, callback) {
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["", params]}, callback);
    }

    $scope.play = function play() { // toggle
        $scope.queryPlayer(["play", ""]);
        //$scope.getStatus();
    };

    $scope.playPause = function playPause() { // toggle
        var newplaying = $scope.playing ? "1" : "0";
        $scope.playing = !$scope.playing;
        $scope.queryPlayer(["pause",newplaying]);
        //$scope.getStatus();
    };
    $scope.backward = function backward() {
        $scope.queryPlayer(["button","jump_rew"]);
        //$scope.getStatus();
    };
    $scope.forward = function forward() {
        $scope.queryPlayer(["button","jump_fwd"]);
        //$scope.getStatus();
    };
    $scope.toggleShuffle = function toggleShuffle() {
        // 0 = disabled, 1 = per song, 2 = per album (unused)
        var newshuffle = $scope.shuffle == "0" ? "1" : "0";
        $scope.shuffle = newshuffle;
        $scope.queryPlayer(["playlist","shuffle", newshuffle]);
    }

    $scope.powerToggle = function powerToggle() {
        var newpower = $scope.power ? "0" : "1";
        $scope.power = newpower;
        $scope.queryPlayer(["power", newpower]);
        //$scope.getStatus();
    };
    $scope.powerOn = function powerOn() {
        $scope.queryPlayer(["power","1"]);
        //$scope.getStatus();
    };
    $scope.volumeUp = function volup() {
        $scope.queryPlayer(["mixer","volume", "+2.5"]);
    };
    $scope.volumeDown = function voldown() {
        $scope.queryPlayer(["mixer","volume", "-2.5"]);
    };

    $scope.changeWindow = function changeWindow(name) {
        if (['play', 'music', 'favorites', 'settings'].indexOf(name) !== -1) {
            $scope.current_window = name;
        }
    }
    $scope.windowTitle = function(t) {
        function capitalize(s) {
            return s.substr(0,1).toUpperCase() + s.substr(1);
        }
        switch (t) {
            case "play":
                return "Now playing"
            break;
            default:
                return capitalize(t);
        }
    }

    // CSS functions XXX rewrite with ng-show
    $scope.CSS_Enabled = function() {
        $scope.active = true;
    };
    $scope.CSS_Playing = function() {
        return $scope.playing ? 'media-pause' : 'media-play';
    };
    $scope.CSS_Shuffle = function() {
        return $scope.shuffle ? 'media-shuffleon' : 'media-shuffleoff';
    };

    $scope.CSS_Power = function() {
        return $scope.power ? "brightness" : "lower-brightness";

    }

    $scope.CSS_window = function CSS_window(name) {
        var sb = document.getElementById("sidebar");
        var scope = angular.element(sb).scope();
        return (name == $scope.current_window) ? "" : "hiddenwindow"
    }

/*

*/

}]);

squeezefox.controller('PlayerStatusCtrl', ['$scope', '$http', '$interval', function ($scope, $http, $interval) {
    // defaults
    var lastUpdate       = 0;
    $scope.playerTitle   = "";
    $scope.currentArtist = "";
    $scope.currentTitle  = "";
    $scope.artworkURL    = "img/cover-missing.png";
    $scope.showPlaylist  = false;

    // Update Status
    $scope.getStatus = function getStatus() {
        //XXX replace 50 with max(50,playlistsize)
        if ($scope.$parent.hidden || typeof $scope.server.addr == 'undefined' || typeof $scope.server.port == 'undefined') {
             /* skips XHR when app is minimized, this is set
              * outside of angular with the page visibility api.
              * (see bottom of this file)
             */
            return;
            }
        $scope.queryPlayer(["status","-", 50, "tags:gABbehldiqtyrSuojcKLNJ"], function(xhr) {
            //xhr.response.result.mode (play, stop, pause)
            var rs = xhr.response.result;
            $scope.playerTitle              = rs.current_title;
            $scope.$parent.playing          = (rs.mode == "play");
            $scope.$parent.active           = true;
            $scope.$parent.power            = rs.power;
            $scope.$parent.shuffle          = rs['playlist shuffle'];
            $scope.repeat                   = rs['playlist repeat'];
            $scope.$parent.playlist.list    = rs.playlist_loop;
            $scope.$parent.playlist.current = rs.playlist_cur_index;
            var currentlyPlaying;
            for (var entry of $scope.$parent.playlist.list) {
                if (entry['playlist index'] == $scope.$parent.playlist.current) {
                    var currentlyPlaying = entry;
                    $scope.currentArtist = currentlyPlaying.artist;
                    $scope.currentTitle = currentlyPlaying.title;
                }
            }
            if ('remoteMeta' in rs) {
                var rm = rs.remoteMeta; //$scope.playlist.list[$scope.playlist.current];
                $scope.artworkURL = rm.artwork_url;
            }
            else if (rs.playlist_loop[rs.playlist_cur_index].coverart == "1") {
                $scope.artworkURL = "http://"+$scope.server.addr+':'+$scope.server.port+"/music/"+rs.playlist_loop[rs.playlist_cur_index].coverid+"/cover_300x300";
            }
            else {
                $scope.artworkURL = "img/cover-missing.png";
            }
            lastUpdate = Date.now();
        });
    }
    $scope.refresher = undefined;
    if (typeof $scope.refresher == "undefined") {
        $scope.getStatus();
        $scope.refresher = $interval(function() { $scope.getStatus(); }, 5000);
    }

    $scope.transitionToggle = function transitionToggle() {
        $scope.showPlaylist = $scope.showPlaylist ? false : true;
    }
    $scope.CSS_transition = function CSS_transition() {
        return $scope.showPlaylist ? "performtransition" : "";
    }

    //
    $scope.playItem = function playItem(index) {
        //XXX update playlists and display?
        $scope.queryPlayer(["playlist","index",index,""]);
    }
    $scope.prettyDuration = function prettyDuration(total) {
        function pad(d) {
            if (d < 10) { return '0'+d }
            return d
        }
        if (total == 0) { return; }
            var m = parseInt(total%3600 / 60)
            var s = total % 60
        if (total < 3600) {
            return "("+m+":"+pad(s)+")";
        }
        else {
            var h = parseInt(total / 3600);
            return "("+h+":"+pad(m)+":"+pad(s)+")";
        }
    }
}]);
squeezefox.controller('MusicSearchCtrl', ['$scope', function ($scope) {
    $scope.searchterm = "";
    $scope.searchresults = []
    $scope.searchdetails = {};
    $scope.showTrackDialog = false;
    $scope.dialogItem = {};
    $scope.search = function search(term) {
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["",["search", "0","20","term:"+term]]}, function(xhr) {
            var tracks = []
            if ('tracks_loop' in xhr.response.result) {
                tracks = xhr.response.result.tracks_loop; // array with objects that have track_id, track properties
            }
            $scope.searchresults = tracks;
            // fill in details for list (e.g. artist)
            for (var item of tracks) {
                $scope.JSONRPC({"id":1,"method":"slim.request","params":["",["songinfo", "0","11","track_id:"+item.track_id]]}, function(xhr) {
                    var songinfo = xhr.response.result.songinfo_loop;
                    $scope.searchdetails[parseInt(songinfo[0].id)] = {
                        title: songinfo[1].title, artist: songinfo[2].artist,
                        coverid: songinfo[3].coverid, duration: songinfo[4].duration,
                        album_id: songinfo[5].album_id,
                        album: songinfo[5].album,
                        coverurl: "http://"+$scope.server.addr+':'+$scope.server.port+"/music/"+songinfo[3].coverid+"/cover_150x150_o" };
                });
            }
        });
    }
    $scope.trackDialog = function trackDialog(item) {
        $scope.dialogItem = item;
        $scope.showTrackDialog = true;
    }
    $scope.addItem = function addItem(item) { // add to queue
        $scope.showTrackDialog=false;
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["00:04:20:2b:39:ec",["playlist","addtracks","track.titlesearch="+item.track]]})
    }
    $scope.playItem = function playItem(item) { // play now
        $scope.showTrackDialog=false;
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["00:04:20:2b:39:ec",["playlist","loadtracks","track.titlesearch="+item.track]]})

    }
}]);
squeezefox.controller('FavoritesCtrl', ['$scope', function ($scope) {
    $scope.favorites = []
    localforage.getItem("favorites", function (cachedFavorites) {
        $scope.favorites = cachedFavorites || [];
    });
    var triedfavorites = false;
    if (triedfavorites == false) {
        if ($scope.selectedPlayer.playerid !== "") {
            triedfavorites = true;
            $scope.JSONRPC({"id":1,"method":"slim.request","params": [$scope.selectedPlayer.playerid, ["favorites","items","","9999"]]}, function(xhr) {
                $scope.favorites = xhr.response.result.loop_loop;
                localforage.setItem("favorites", xhr.response.result.loop_loop);
            });
        }
    }
    $scope.playFavorite = function playFavorite(id) {
        $scope.JSONRPC({"id":1,"method":"slim.request","params": [$scope.selectedPlayer.playerid, ["favorites","playlist","play","item_id:"+id]]});
    }

    $scope.playDeezer = function() {
        var x = new XMLHttpRequest();
        x.open("GET",
        "http://192.168.235.2:9000/plugins/deezer/index.html?action=playall&index=4cd7c293.3.0.1&player=00%3A04%3A20%3A2b%3A39%3Aec&sess=&start=&_dc=1403809424200"
        );
        x.send();

    }
}]);

squeezefox.controller('SettingsCtrl', ['$scope', function ($scope) {
    $scope.players = [];
    localforage.getItem("players", function (cachedPlayers) {
        $scope.players = cachedPlayers || [];
    });
    /*     {
            "model" : "baby",
            "connected" : 1,
            "displaytype" : "none",
            "seq_no" : "297",
            "ip" : "192.168.235.180:54444",
            "power" : 0,
            "uuid" : "3e08aeb1e28940bfc8e73028939025f8",
            "name" : "Küchenradio",
            "isplayer" : 1,
            "canpoweroff" : 1,
            "playerid" : "00:04:20:2b:39:ec"
         }, */

    $scope.tryServer = function tryServer() {
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["",["serverstatus",0,999]]}, function(xhr) {
            $scope.$parent.active = true; // errback and feedback.
            $scope.players = xhr.response.result.players_loop;
            localforage.setItem("players", xhr.response.result.players_loop);
        });
    }
}]);

/*
angular.element(document).ready(function() {
    document.addEventListener("visibilitychange", function() {
        // used to limit getStatus XHR
        angular.element(document.body).scope().hidden = document.hidden;
    }, false);

    // fire a first getStatus asap:
    angular.element(document.querySelector("#window-play")).scope().getStatus
});
*/
<commit_msg>refactor musicsearchctrl<commit_after>"use strict";
var squeezefox = angular.module('Squeezefox', ['ngAnimate'])
.config([
    '$compileProvider',
    function( $compileProvider )
    {
        $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|app):/);
    }
]);

squeezefox.controller('WindowCtrl', ['$scope', function ($scope) {

    $scope.players = [];
    $scope.selectedPlayer = {playerid: "",
                             name: ""};

                                //{playerid: "00:04:20:2b:39:ec", name: ''}; //XXX make dynamic
    $scope.current_window = "play";
    $scope.hidden = false;
    $scope.server = { addr: '', port: '', retries: 0 }
    localforage.getItem('server').then(function (cachedServer) {
        if (typeof cachedServer != 'undefined') {
            $scope.server = cachedServer;
        }
    });
    localforage.getItem('players').then(function (cachedPlayers) {
        $scope.players = cachedPlayers || [];
    })
    .then(function(){
        localforage.getItem('selectedPlayer', function(cachedSelectedPlayer) {
            /*
            * this is because the <select> tag will only remember the selection if ng-model is member of the array in ng-options (comparison by reference)
            * so we have to search the equal reference by eg playerid
            */
            for (var i = 0; i < $scope.players.length; i++) {
                if ($scope.players[i].playerid == cachedSelectedPlayer.playerid) {
                    $scope.selectedPlayer = $scope.players[i];
                    return;
                }
            }
        });
    });

    $scope.playlist = {current: 0, list: []};
    $scope.active   = false;
    $scope.power    = 0;
    $scope.playing  = false;
    $scope.shuffle  = 0;

    $scope.JSONRPC = function JSONRPC(payload, callback) {
        var xhr = new XMLHttpRequest({mozSystem: true});
        xhr.open("POST", "http://"+$scope.server.addr+':'+$scope.server.port+"/jsonrpc.js");
        xhr.responseType = "json";
        xhr.send(JSON.stringify(payload));
        xhr.onload = function() {
            localforage.setItem("server", $scope.server);
            localforage.setItem("selectedPlayer", $scope.selectedPlayer);
            $scope.active = true;
            // count retries for error handling? yagni?
            if ($scope.server.retries > 0) {
                $scope.server.retries = 0;
            }
            if (callback) { callback(this); }
        };
        xhr.onerror = function (e) {
            // XXX general error handling? provide another callback?
            $scope.server.retries++;
        };
    };

    /*
    * wrapper to JSONRPC. do a slim request on the current set playerid
    * params is a list, eg: ["play", ""]
    */
    $scope.queryPlayer = function (params, callback, playerid) {
        playerid = typeof playerid !== 'undefined' ? playerid : $scope.selectedPlayer.playerid;
        $scope.JSONRPC({"id":1,"method":"slim.request","params":[playerid, params]}, callback);
    }
    /*
    * do a query with empty playerid
    */
    $scope.queryServer = function (params, callback) {
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["", params]}, callback);
    }

    $scope.play = function play() { // toggle
        $scope.queryPlayer(["play", ""]);
        //$scope.getStatus();
    };

    $scope.playPause = function playPause() { // toggle
        var newplaying = $scope.playing ? "1" : "0";
        $scope.playing = !$scope.playing;
        $scope.queryPlayer(["pause",newplaying]);
        //$scope.getStatus();
    };
    $scope.backward = function backward() {
        $scope.queryPlayer(["button","jump_rew"]);
        //$scope.getStatus();
    };
    $scope.forward = function forward() {
        $scope.queryPlayer(["button","jump_fwd"]);
        //$scope.getStatus();
    };
    $scope.toggleShuffle = function toggleShuffle() {
        // 0 = disabled, 1 = per song, 2 = per album (unused)
        var newshuffle = $scope.shuffle == "0" ? "1" : "0";
        $scope.shuffle = newshuffle;
        $scope.queryPlayer(["playlist","shuffle", newshuffle]);
    }

    $scope.powerToggle = function powerToggle() {
        var newpower = $scope.power ? "0" : "1";
        $scope.power = newpower;
        $scope.queryPlayer(["power", newpower]);
        //$scope.getStatus();
    };
    $scope.powerOn = function powerOn() {
        $scope.queryPlayer(["power","1"]);
        //$scope.getStatus();
    };
    $scope.volumeUp = function volup() {
        $scope.queryPlayer(["mixer","volume", "+2.5"]);
    };
    $scope.volumeDown = function voldown() {
        $scope.queryPlayer(["mixer","volume", "-2.5"]);
    };

    $scope.changeWindow = function changeWindow(name) {
        if (['play', 'music', 'favorites', 'settings'].indexOf(name) !== -1) {
            $scope.current_window = name;
        }
    }
    $scope.windowTitle = function(t) {
        function capitalize(s) {
            return s.substr(0,1).toUpperCase() + s.substr(1);
        }
        switch (t) {
            case "play":
                return "Now playing"
            break;
            default:
                return capitalize(t);
        }
    }

    // CSS functions XXX rewrite with ng-show
    $scope.CSS_Enabled = function() {
        $scope.active = true;
    };
    $scope.CSS_Playing = function() {
        return $scope.playing ? 'media-pause' : 'media-play';
    };
    $scope.CSS_Shuffle = function() {
        return $scope.shuffle ? 'media-shuffleon' : 'media-shuffleoff';
    };

    $scope.CSS_Power = function() {
        return $scope.power ? "brightness" : "lower-brightness";

    }

    $scope.CSS_window = function CSS_window(name) {
        var sb = document.getElementById("sidebar");
        var scope = angular.element(sb).scope();
        return (name == $scope.current_window) ? "" : "hiddenwindow"
    }

/*

*/

}]);

squeezefox.controller('PlayerStatusCtrl', ['$scope', '$http', '$interval', function ($scope, $http, $interval) {
    // defaults
    var lastUpdate       = 0;
    $scope.playerTitle   = "";
    $scope.currentArtist = "";
    $scope.currentTitle  = "";
    $scope.artworkURL    = "img/cover-missing.png";
    $scope.showPlaylist  = false;

    // Update Status
    $scope.getStatus = function getStatus() {
        //XXX replace 50 with max(50,playlistsize)
        if ($scope.$parent.hidden || typeof $scope.server.addr == 'undefined' || typeof $scope.server.port == 'undefined') {
             /* skips XHR when app is minimized, this is set
              * outside of angular with the page visibility api.
              * (see bottom of this file)
             */
            return;
            }
        $scope.queryPlayer(["status","-", 50, "tags:gABbehldiqtyrSuojcKLNJ"], function(xhr) {
            //xhr.response.result.mode (play, stop, pause)
            var rs = xhr.response.result;
            $scope.playerTitle              = rs.current_title;
            $scope.$parent.playing          = (rs.mode == "play");
            $scope.$parent.active           = true;
            $scope.$parent.power            = rs.power;
            $scope.$parent.shuffle          = rs['playlist shuffle'];
            $scope.repeat                   = rs['playlist repeat'];
            $scope.$parent.playlist.list    = rs.playlist_loop;
            $scope.$parent.playlist.current = rs.playlist_cur_index;
            var currentlyPlaying;
            for (var entry of $scope.$parent.playlist.list) {
                if (entry['playlist index'] == $scope.$parent.playlist.current) {
                    var currentlyPlaying = entry;
                    $scope.currentArtist = currentlyPlaying.artist;
                    $scope.currentTitle = currentlyPlaying.title;
                }
            }
            if ('remoteMeta' in rs) {
                var rm = rs.remoteMeta; //$scope.playlist.list[$scope.playlist.current];
                $scope.artworkURL = rm.artwork_url;
            }
            else if (rs.playlist_loop[rs.playlist_cur_index].coverart == "1") {
                $scope.artworkURL = "http://"+$scope.server.addr+':'+$scope.server.port+"/music/"+rs.playlist_loop[rs.playlist_cur_index].coverid+"/cover_300x300";
            }
            else {
                $scope.artworkURL = "img/cover-missing.png";
            }
            lastUpdate = Date.now();
        });
    }
    $scope.refresher = undefined;
    if (typeof $scope.refresher == "undefined") {
        $scope.getStatus();
        $scope.refresher = $interval(function() { $scope.getStatus(); }, 5000);
    }

    $scope.transitionToggle = function transitionToggle() {
        $scope.showPlaylist = $scope.showPlaylist ? false : true;
    }
    $scope.CSS_transition = function CSS_transition() {
        return $scope.showPlaylist ? "performtransition" : "";
    }

    //
    $scope.playItem = function playItem(index) {
        //XXX update playlists and display?
        $scope.queryPlayer(["playlist","index",index,""]);
    }
    $scope.prettyDuration = function prettyDuration(total) {
        function pad(d) {
            if (d < 10) { return '0'+d }
            return d
        }
        if (total == 0) { return; }
            var m = parseInt(total%3600 / 60)
            var s = total % 60
        if (total < 3600) {
            return "("+m+":"+pad(s)+")";
        }
        else {
            var h = parseInt(total / 3600);
            return "("+h+":"+pad(m)+":"+pad(s)+")";
        }
    }
}]);
squeezefox.controller('MusicSearchCtrl', ['$scope', function ($scope) {
    $scope.searchterm = "";
    $scope.searchresults = []
    $scope.searchdetails = {};
    $scope.showTrackDialog = false;
    $scope.dialogItem = {};
    $scope.search = function search(term) {
        $scope.queryServer(["search", "0","20","term:"+term], function(xhr) {
            var tracks = []
            if ('tracks_loop' in xhr.response.result) {
                tracks = xhr.response.result.tracks_loop; // array with objects that have track_id, track properties
            }
            $scope.searchresults = tracks;
            // fill in details for list (e.g. artist)
            for (var item of tracks) {
                $scope.queryServer(["songinfo", "0","11","track_id:"+item.track_id], function(xhr) {
                    var songinfo = xhr.response.result.songinfo_loop;
                    $scope.searchdetails[parseInt(songinfo[0].id)] = {
                        title: songinfo[1].title, artist: songinfo[2].artist,
                        coverid: songinfo[3].coverid, duration: songinfo[4].duration,
                        album_id: songinfo[5].album_id,
                        album: songinfo[5].album,
                        coverurl: "http://"+$scope.server.addr+':'+$scope.server.port+"/music/"+songinfo[3].coverid+"/cover_150x150_o" };
                });
            }
        });
    }
    $scope.trackDialog = function trackDialog(item) {
        $scope.dialogItem = item;
        $scope.showTrackDialog = true;
    }
    $scope.addItem = function addItem(item) { // add to queue
        $scope.showTrackDialog=false;
        $scope.queryPlayer(["playlist","addtracks","track.titlesearch="+(item.track ? item.track : item.title)]); // what if 2 tracks same name? add contributor.namesearch= property? API = fail..
    }
    $scope.playItem = function playItem(item) { // play now
        $scope.showTrackDialog=false;
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["00:04:20:2b:39:ec",["playlist","loadtracks","track.titlesearch="+item.track]]})

    }
}]);
squeezefox.controller('FavoritesCtrl', ['$scope', function ($scope) {
    $scope.favorites = []
    localforage.getItem("favorites", function (cachedFavorites) {
        $scope.favorites = cachedFavorites || [];
    });
    var triedfavorites = false;
    if (triedfavorites == false) {
        if ($scope.selectedPlayer.playerid !== "") {
            triedfavorites = true;
            $scope.JSONRPC({"id":1,"method":"slim.request","params": [$scope.selectedPlayer.playerid, ["favorites","items","","9999"]]}, function(xhr) {
                $scope.favorites = xhr.response.result.loop_loop;
                localforage.setItem("favorites", xhr.response.result.loop_loop);
            });
        }
    }
    $scope.playFavorite = function playFavorite(id) {
        $scope.JSONRPC({"id":1,"method":"slim.request","params": [$scope.selectedPlayer.playerid, ["favorites","playlist","play","item_id:"+id]]});
    }

    $scope.playDeezer = function() {
        var x = new XMLHttpRequest();
        x.open("GET",
        "http://192.168.235.2:9000/plugins/deezer/index.html?action=playall&index=4cd7c293.3.0.1&player=00%3A04%3A20%3A2b%3A39%3Aec&sess=&start=&_dc=1403809424200"
        );
        x.send();

    }
}]);

squeezefox.controller('SettingsCtrl', ['$scope', function ($scope) {
    $scope.players = [];
    localforage.getItem("players", function (cachedPlayers) {
        $scope.players = cachedPlayers || [];
    });
    /*     {
            "model" : "baby",
            "connected" : 1,
            "displaytype" : "none",
            "seq_no" : "297",
            "ip" : "192.168.235.180:54444",
            "power" : 0,
            "uuid" : "3e08aeb1e28940bfc8e73028939025f8",
            "name" : "Küchenradio",
            "isplayer" : 1,
            "canpoweroff" : 1,
            "playerid" : "00:04:20:2b:39:ec"
         }, */

    $scope.tryServer = function tryServer() {
        $scope.JSONRPC({"id":1,"method":"slim.request","params":["",["serverstatus",0,999]]}, function(xhr) {
            $scope.$parent.active = true; // errback and feedback.
            $scope.players = xhr.response.result.players_loop;
            localforage.setItem("players", xhr.response.result.players_loop);
        });
    }
}]);

/*
angular.element(document).ready(function() {
    document.addEventListener("visibilitychange", function() {
        // used to limit getStatus XHR
        angular.element(document.body).scope().hidden = document.hidden;
    }, false);

    // fire a first getStatus asap:
    angular.element(document.querySelector("#window-play")).scope().getStatus
});
*/
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert'),
  Gpio = require('../').Gpio,
  iv,
  led = new Gpio(18, {mode: Gpio.OUTPUT}),
  frequency,
  dutyCycle;

assert.strictEqual(led.getPwmRange(), 255, 'expected pwm range to be 255');
assert.strictEqual(led.getPwmRealRange(), 250, 'expected pwm real range to be 250');
assert.strictEqual(led.getPwmFrequency(), 800, 'expected get pwm frequency to be 800');

led.pwmRange(125);
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 250, 'expected pwm real range to be 250');
assert.strictEqual(led.getPwmFrequency(), 800, 'expected get pwm frequency to be 800');

led.pwmFrequency(2000)
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 100, 'expected pwm real range to be 100');
assert.strictEqual(led.getPwmFrequency(), 2000, 'expected get pwm frequency to be 2000');

dutyCycle = Math.floor(led.getPwmRange() / 2);
led.pwmWrite(dutyCycle);
assert.strictEqual(led.getPwmDutyCycle(), dutyCycle, 'expected duty cycle to be ' + dutyCycle);

led.hardwarePwmWrite(1e7, 500000);
assert.strictEqual(led.getPwmRange(), 1e6, 'expected pwm range to be 1e6');
assert.strictEqual(led.getPwmRealRange(), 25, 'expected pwm real range to be 25');
assert.strictEqual(led.getPwmFrequency(), 1e7, 'expected get pwm frequency to be 1e7');
assert.strictEqual(led.getPwmDutyCycle(), 500000, 'expected duty cycle to be 500000');

led.digitalWrite(0);
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 100, 'expected pwm real range to be 100');
assert.strictEqual(led.getPwmFrequency(), 2000, 'expected get pwm frequency to be 2000');

<commit_msg>redundant var removed<commit_after>'use strict';

var assert = require('assert'),
  Gpio = require('../').Gpio,
  iv,
  led = new Gpio(18, {mode: Gpio.OUTPUT}),
  dutyCycle;

assert.strictEqual(led.getPwmRange(), 255, 'expected pwm range to be 255');
assert.strictEqual(led.getPwmRealRange(), 250, 'expected pwm real range to be 250');
assert.strictEqual(led.getPwmFrequency(), 800, 'expected get pwm frequency to be 800');

led.pwmRange(125);
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 250, 'expected pwm real range to be 250');
assert.strictEqual(led.getPwmFrequency(), 800, 'expected get pwm frequency to be 800');

led.pwmFrequency(2000)
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 100, 'expected pwm real range to be 100');
assert.strictEqual(led.getPwmFrequency(), 2000, 'expected get pwm frequency to be 2000');

dutyCycle = Math.floor(led.getPwmRange() / 2);
led.pwmWrite(dutyCycle);
assert.strictEqual(led.getPwmDutyCycle(), dutyCycle, 'expected duty cycle to be ' + dutyCycle);

led.hardwarePwmWrite(1e7, 500000);
assert.strictEqual(led.getPwmRange(), 1e6, 'expected pwm range to be 1e6');
assert.strictEqual(led.getPwmRealRange(), 25, 'expected pwm real range to be 25');
assert.strictEqual(led.getPwmFrequency(), 1e7, 'expected get pwm frequency to be 1e7');
assert.strictEqual(led.getPwmDutyCycle(), 500000, 'expected duty cycle to be 500000');

led.digitalWrite(0);
assert.strictEqual(led.getPwmRange(), 125, 'expected pwm range to be 125');
assert.strictEqual(led.getPwmRealRange(), 100, 'expected pwm real range to be 100');
assert.strictEqual(led.getPwmFrequency(), 2000, 'expected get pwm frequency to be 2000');

<|endoftext|>


<commit_before>angular.module('app.controllers', ['angular-hmac-sha512', 'app.utility'])

    .controller('AppCtrl', function ($scope, $state, $rootScope, $crypthmac, Utility, $ionicPopup) {

        /*$scope.doRefresh=function(){
         $rootScope.$broadcast("onRefreshClick");
         }*/

        $rootScope.logout = function () {
            //Take confirmation
            var confirmPopup = $ionicPopup.confirm({
                title: 'Logout',
                template: 'Are you sure you want to logout?'
            });
            confirmPopup.then(function (res) {
                if (res) {
                    //console.log('You are sure');
                    Utility.clarSesion();
                    $state.go("login");
                }
            });
        };

        //Show toast
        $rootScope.showToast = function (message) {
            alert(message);
        };

        //Show alert
        $rootScope.showToast = function (message) {
            alert(message);
        };

        //Encrypt
        $rootScope.encrypt = function (text) {
            $crypthmac.encrypt(text, "");
        }
    })

    .controller('LoginCtrl', function ($scope, $state, $rootScope, $log, AppService, Utility) {
        $scope.user =
        {
            email: "", //"ahamad.parwej@gmail.com"
            password: ""
        };

        $scope.login = function () {

            ////Validation
            //if (Utility.isEmpty($scope.user.email) || (!Utility.isValidEmail($scope.user.email))) {
            //    $rootScope.showToast("Please enter email");
            //    return;
            //}
            //
            //if (Utility.isEmpty($scope.user.password)) {
            //    $rootScope.showToast("Please enter password ");
            //    return;
            //}

            var userName = $rootScope.encrypt("ravindranathakila@gmail.com");//$rootScope.encrypt($scope.user.email);
            var password = $rootScope.encrypt("wwwwww");//$rootScope.encrypt($scope.user.password);

            //Login
            AppService.login(userName, password)
                .then(
                function (response) {
                    try {
                        var returnData = response.data.returnValue.data[0];
                        $log.log(JSON.stringify(response.data));
                        if (returnData.status == "OK") {
                            //Set token
                            Utility.setToken(returnData.tokenHash);
                            Utility.setHumanId(returnData.humanIdHash);

                            $state.go("app.news");
                        }
                        else {
                            $rootScope.showToast(response.data.returnMessage);
                        }

                    }
                    catch (ex) {
                        $log.log("Login => Error : " + JSON.stringify(ex));
                    }
                },

                function (err) {
                    $rootScope.showToast("Error occurred, try agian :" + JSON.stringify(err));
                }
            )

        }
    })

    .controller('RegisterCtrl', function ($scope, $state, $rootScope, AppService, Utility) {
        $scope.user =
        {
            email: "",
            password: "",
            confirm: ""
        };

        $scope.register = function () {

            //Validation
            if (Utility.isEmpty($scope.user.email) || (!Utility.isValidEmail($scope.user.email))) {
                $rootScope.showToast("Please enter email");
                return;
            }

            if (Utility.isEmpty($scope.user.password)) {
                $rootScope.showToast("Please enter password ");
                return;
            }

            if (Utility.isEmpty($scope.user.confirm)) {
                $rootScope.showToast("Please enter confirm password ");
                return;
            }

            if ($scope.user.password != $scope.user.confirm) {
                $rootScope.showToast("Confirm password doesn't matched");
                return;
            }

            var userName = $rootScope.encrypt($scope.user.email);
            var password = $rootScope.encrypt($scope.user.password);

            //Login
            AppService.register(userName, password, $scope.user.email)
                .then(
                function (response) {
                    //$rootScope.showToast(JSON.stringify(response));
                    $rootScope.showToast("Registed sucessfully");
                    $state.go("login");
                },

                function (err) {
                    $rootScope.showToast("Error occurred, try agian :" + JSON.stringify(err));
                }
            );

            //$state.go("app.home");
        }
    })

    .controller('NewsCtrl', function ($scope, $rootScope, AppService, Utility) {

        //$ionicSideMenuDelegate.canDragContent(false);

        //listen refresh button
        $scope.doRefresh = function () {
            loadFeed();
        };

        $scope.feeds = [];

        //load rss feed
        var loadFeed = function () {
            $scope.feeds = [];
            AppService.newsFeed(Utility.getHumanId())
                .then(
                function (res) {
                    if (res && res.data && res.data.returnValue && res.data.returnValue.data) {

                        const items = res.data.returnValue.data;

                        items.forEach(function (element) {
                            element.title =  element.title.replace(/[|&;$%@"<>()+,]/g, "");

                        });

                        $scope.feeds = items;

                        /*
                         feedItemTitle.text(item.title.replace(/[|&;$%@"<>()+,]/g, ""));//http://stackoverflow.com/questions/3780696/javascript-string-replace-with-regex-to-strip-off-illegal-characters

                         */

                        /*
                         data.sort(function (a, b) {//http://stackoverflow.com/questions/4222690/sorting-a-json-object-in-javascript
                         var a1st = -1; // negative value means left item should appear first
                         var b1st = 1; // positive value means right item should appear first
                         var equal = 0; // zero means objects are equal

                         if (b.shocks < a.shocks) {
                         return b1st;
                         }
                         else if (a.shocks < b.shocks) {
                         return a1st;
                         }
                         else {
                         return equal;
                         }
                         }
                         );
                         */
                    }
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try again" + JSON.stringify(err));
                }
            );
        };

        loadFeed();

        //Mark read
        $scope.onReadClick = function (feed) {
            window.open(feed.link, '_blank', 'location=yes');
            AppService.readNews(Utility.getHumanId(), feed.link)
                .then(
                function (res) {
                    //Ignore
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                }
            );
            //'Checking for any updates (News Mute)'
        };

        //Mark share
        $scope.onShareClick = function (feed) {
            if ($rootScope.isValidURL(feed)) {
                AppService.shareNews(Utility.getHumanId(), feed.link)
                    .then(
                    function (res) {
                        if (res && res.data && res.data.returnValue && res.data.returnValue.data) {
                            $scope.feeds = res.data.returnValue.data;
                        }
                    },
                    function (err) {
                        $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                    }
                );
            } else {
                $rootScope.showTaost('Sorry :-( This link is not recognized by News Mute');
            }
        };

        $scope.feedItem = true;

        //Mark mute
        $scope.onMuteClick = function (feed) {
            AppService.muteNews(Utility.getHumanId(), feed.link)
                .then(
                function (res) {
                    //$scope.feedItem = false;
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                }
            );
        }

    })
    .directive('feedDescription', function ($timeout) {
        return {
            template: "

",
            link: function (scope, element, attr) {
                if (scope.$last === true) {
                    $timeout(function () {
                        console.log("Description:" + element);

                        angular.forEach(element.find("a"), function (value, index) {

                            var a = angular.element(value);

                            var href = a.attr("href");

                            a.attr("href", "intent_open_link('" + href + "');")
                                .removeAttr("href");
                        });

                    });
                }
            }
        }
    })

    .controller('DirectoryCtrl', function ($scope, $state, $rootScope, FeedUrls, $ionicSideMenuDelegate, AppService, Utility) {

        alert(JSON.stringify(AppService.getUserLocation()));

        //Disable menu
        $ionicSideMenuDelegate.canDragContent(false);
        //Load feed urls
        $scope.feedList = FeedUrls.getIndustriesFeedsUrl();

        //On click link
        $scope.onFeedToggle = function (feed) {
            //subcribe for feed
            if (feed.checked) {
                var url = feed.feeds[0];
                AppService.subscribeFeed(Utility.getHumanId(), url)
                    .then(
                    function (res) {
                        //alert(JSON.stringify(res));
                        //$rootScope.showToast("Subscribed successfully");
                    },
                    function (err) {
                        alert(JSON.stringify(err));
                    }
                );

            }
            //TODO: Unsubcribe
            //$state.go("app.news",{feedUrl : feed.feeds[0]});
        }

    })

;
<commit_msg>Feed item sorting added<commit_after>angular.module('app.controllers', ['angular-hmac-sha512', 'app.utility'])

    .controller('AppCtrl', function ($scope, $state, $rootScope, $crypthmac, Utility, $ionicPopup) {

        /*$scope.doRefresh=function(){
         $rootScope.$broadcast("onRefreshClick");
         }*/

        $rootScope.logout = function () {
            //Take confirmation
            var confirmPopup = $ionicPopup.confirm({
                title: 'Logout',
                template: 'Are you sure you want to logout?'
            });
            confirmPopup.then(function (res) {
                if (res) {
                    //console.log('You are sure');
                    Utility.clarSesion();
                    $state.go("login");
                }
            });
        };

        //Show toast
        $rootScope.showToast = function (message) {
            alert(message);
        };

        //Show alert
        $rootScope.showToast = function (message) {
            alert(message);
        };

        //Encrypt
        $rootScope.encrypt = function (text) {
            $crypthmac.encrypt(text, "");
        }
    })

    .controller('LoginCtrl', function ($scope, $state, $rootScope, $log, AppService, Utility) {
        $scope.user =
        {
            email: "", //"ahamad.parwej@gmail.com"
            password: ""
        };

        $scope.login = function () {

            ////Validation
            //if (Utility.isEmpty($scope.user.email) || (!Utility.isValidEmail($scope.user.email))) {
            //    $rootScope.showToast("Please enter email");
            //    return;
            //}
            //
            //if (Utility.isEmpty($scope.user.password)) {
            //    $rootScope.showToast("Please enter password ");
            //    return;
            //}

            var userName = $rootScope.encrypt("ravindranathakila@gmail.com");//$rootScope.encrypt($scope.user.email);
            var password = $rootScope.encrypt("wwwwww");//$rootScope.encrypt($scope.user.password);

            //Login
            AppService.login(userName, password)
                .then(
                function (response) {
                    try {
                        var returnData = response.data.returnValue.data[0];
                        $log.log(JSON.stringify(response.data));
                        if (returnData.status == "OK") {
                            //Set token
                            Utility.setToken(returnData.tokenHash);
                            Utility.setHumanId(returnData.humanIdHash);

                            $state.go("app.news");
                        }
                        else {
                            $rootScope.showToast(response.data.returnMessage);
                        }

                    }
                    catch (ex) {
                        $log.log("Login => Error : " + JSON.stringify(ex));
                    }
                },

                function (err) {
                    $rootScope.showToast("Error occurred, try agian :" + JSON.stringify(err));
                }
            )

        }
    })

    .controller('RegisterCtrl', function ($scope, $state, $rootScope, AppService, Utility) {
        $scope.user =
        {
            email: "",
            password: "",
            confirm: ""
        };

        $scope.register = function () {

            //Validation
            if (Utility.isEmpty($scope.user.email) || (!Utility.isValidEmail($scope.user.email))) {
                $rootScope.showToast("Please enter email");
                return;
            }

            if (Utility.isEmpty($scope.user.password)) {
                $rootScope.showToast("Please enter password ");
                return;
            }

            if (Utility.isEmpty($scope.user.confirm)) {
                $rootScope.showToast("Please enter confirm password ");
                return;
            }

            if ($scope.user.password != $scope.user.confirm) {
                $rootScope.showToast("Confirm password doesn't matched");
                return;
            }

            var userName = $rootScope.encrypt($scope.user.email);
            var password = $rootScope.encrypt($scope.user.password);

            //Login
            AppService.register(userName, password, $scope.user.email)
                .then(
                function (response) {
                    //$rootScope.showToast(JSON.stringify(response));
                    $rootScope.showToast("Registed sucessfully");
                    $state.go("login");
                },

                function (err) {
                    $rootScope.showToast("Error occurred, try agian :" + JSON.stringify(err));
                }
            );

            //$state.go("app.home");
        }
    })

    .controller('NewsCtrl', function ($scope, $rootScope, AppService, Utility) {

        //$ionicSideMenuDelegate.canDragContent(false);

        //listen refresh button
        $scope.doRefresh = function () {
            loadFeed();
        };

        $scope.feeds = [];

        //load rss feed
        var loadFeed = function () {
            $scope.feeds = [];
            AppService.newsFeed(Utility.getHumanId())
                .then(
                function (res) {
                    if (res && res.data && res.data.returnValue && res.data.returnValue.data) {

                        const items = res.data.returnValue.data;

                        items.forEach(function (element) {
                            element.title =  element.title.replace(/[|&;$%@"<>()+,]/g, "");

                        });

                        items.sort(function (a, b) {//http://stackoverflow.com/questions/4222690/sorting-a-json-object-in-javascript
                                var a1st = 1; // negative value means left item should appear first
                                var b1st = -1; // positive value means right item should appear first
                                var equal = 0; // zero means objects are equal

                                if (b.shocks < a.shocks) {
                                    return b1st;
                                }
                                else if (a.shocks < b.shocks) {
                                    return a1st;
                                }
                                else {
                                    return equal;
                                }
                            }
                         );

                        $scope.feeds = items;

                    }
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try again" + JSON.stringify(err));
                }
            );
        };

        loadFeed();

        //Mark read
        $scope.onReadClick = function (feed) {
            window.open(feed.link, '_blank', 'location=yes');
            AppService.readNews(Utility.getHumanId(), feed.link)
                .then(
                function (res) {
                    //Ignore
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                }
            );
            //'Checking for any updates (News Mute)'
        };

        //Mark share
        $scope.onShareClick = function (feed) {
            if ($rootScope.isValidURL(feed)) {
                AppService.shareNews(Utility.getHumanId(), feed.link)
                    .then(
                    function (res) {
                        if (res && res.data && res.data.returnValue && res.data.returnValue.data) {
                            $scope.feeds = res.data.returnValue.data;
                        }
                    },
                    function (err) {
                        $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                    }
                );
            } else {
                $rootScope.showTaost('Sorry :-( This link is not recognized by News Mute');
            }
        };

        $scope.feedItem = true;

        //Mark mute
        $scope.onMuteClick = function (feed) {
            AppService.muteNews(Utility.getHumanId(), feed.link)
                .then(
                function (res) {
                    //$scope.feedItem = false;
                },
                function (err) {
                    $rootScope.showTaost("Error occurred, try agian" + JSON.stringify(err));
                }
            );
        }

    })
    .directive('feedDescription', function ($timeout) {
        return {
            template: "

",
            link: function (scope, element, attr) {
                if (scope.$last === true) {
                    $timeout(function () {
                        console.log("Description:" + element);

                        angular.forEach(element.find("a"), function (value, index) {

                            var a = angular.element(value);

                            var href = a.attr("href");

                            a.attr("href", "intent_open_link('" + href + "');")
                                .removeAttr("href");
                        });

                    });
                }
            }
        }
    })

    .controller('DirectoryCtrl', function ($scope, $state, $rootScope, FeedUrls, $ionicSideMenuDelegate, AppService, Utility) {

        alert(JSON.stringify(AppService.getUserLocation()));

        //Disable menu
        $ionicSideMenuDelegate.canDragContent(false);
        //Load feed urls
        $scope.feedList = FeedUrls.getIndustriesFeedsUrl();

        //On click link
        $scope.onFeedToggle = function (feed) {
            //subcribe for feed
            if (feed.checked) {
                var url = feed.feeds[0];
                AppService.subscribeFeed(Utility.getHumanId(), url)
                    .then(
                    function (res) {
                        //alert(JSON.stringify(res));
                        //$rootScope.showToast("Subscribed successfully");
                    },
                    function (err) {
                        alert(JSON.stringify(err));
                    }
                );

            }
            //TODO: Unsubcribe
            //$state.go("app.news",{feedUrl : feed.feeds[0]});
        }

    })

;
<|endoftext|>


<commit_before>define(['js/ui/View'], function(View) {

    return View.inherit('js.core.Window', {

        defaults: {
            tagName: 'div',
            componentClass: 'window',
            closeOnBackdrop: false
        },

        events: [
            "on:backdropClick"
        ],

        ctor: function() {
            this.callBase();

            this.bind("on:backdropClick", this._onbackdropClick, this);
        },

        _onbackdropClick: function(e) {
            if (this.$.closeOnBackdrop) {
                this.close();
            }
        },

        /***
         * shows the window by adding it to the WindowManager
         * @param {Function} [callback]  - the callback which is called when the window gets closed.
         * @param {Boolean} [modal=false]
         *
         * @see js.core.WindowManager
         */
        show: function(callback, modal) {
            this.$stage.$windowManager.show(this, callback, modal);
        },
        /***
         * Calls the show method with modal=true and the callback
         *
         * @param {Function} [callback] - the callback which is called when the window gets closed
         */
        showModal: function(callback) {
            this.show(callback, true);
        },
        /**
         * Closes the window
         *
         * @param state
         */
        close: function(state) {
            this.trigger('close', state);
        },
        /**
         * Renders the window class attribute
         *
         * @param {String} cls
         * @param {String} oldCls
         * @private
         */
        _renderWindowClass: function (cls, oldCls) {
            if (oldCls) {
                this.removeClass(oldCls);
            }

            if (cls) {
                this.addClass(cls);
            }
        }

    });

});<commit_msg>added documentation for the window callback<commit_after>define(['js/ui/View'], function (View) {

    return View.inherit('js.core.Window', {

        defaults: {
            tagName: 'div',
            componentClass: 'window',
            closeOnBackdrop: false
        },

        events: [
            "on:backdropClick"
        ],

        ctor: function () {
            this.callBase();

            this.bind("on:backdropClick", this._onbackdropClick, this);
        },

        _onbackdropClick: function (e) {
            if (this.$.closeOnBackdrop) {
                this.close();
            }
        },

        /***
         * Shows the window by adding it to the WindowManager. You can pass a callback for closing of the window.
         *
         * The callback has the following signature.
         *
         * function(err, window, status){...}
         *
         * @param {Function} [callback]  - the callback which is called when the window gets closed.
         * @param {Boolean} [modal=false]
         *
         * @see js.core.WindowManager
         */
        show: function (callback, modal) {
            this.$stage.$windowManager.show(this, callback, modal);
        },
        /***
         * Calls the show method with modal=true and the callback
         *
         * @param {Function} [callback] - the callback which is called when the window gets closed
         */
        showModal: function (callback) {
            this.show(callback, true);
        },
        /**
         * Closes the window
         *
         * @param state
         */
        close: function (state) {
            this.trigger('close', state);
        },
        /**
         * Renders the window class attribute
         *
         * @param {String} cls
         * @param {String} oldCls
         * @private
         */
        _renderWindowClass: function (cls, oldCls) {
            if (oldCls) {
                this.removeClass(oldCls);
            }

            if (cls) {
                this.addClass(cls);
            }
        }

    });

});<|endoftext|>


<commit_before>var Watcher = require("../lib/watcher").Watcher;
var BuildContext = require("../lib/context").BuildContext;
var ModuleReader = require("../lib/reader").ModuleReader;
var BundleWriter = require("../lib/writer").BundleWriter;
var Pipeline = require("../lib/pipeline").Pipeline;
var makeBundleP = require("../lib/bundle").makeBundleP;
var util = require("../lib/util");
var fs = require("fs");
var Q = require("q");

var path = require("path");
var sourceDir = path.resolve(__dirname, "source");
var outputDir = path.resolve(__dirname, "output");

try {
    fs.mkdirSync(outputDir);
} catch (exists) {
    // pass
}

var watcher = new Watcher(sourceDir);

var debugContext = new BuildContext({
    debug: true
}, watcher, outputDir, []);

var releaseContext = new BuildContext({
    debug: false
}, watcher, outputDir, []);

function getSourceP(id) {
    return this.readFileP(id + ".js");
}

function waitForHelpers(t, helperP) {
    Q.all([
        helperP(debugContext),
        helperP(releaseContext)
    ]).done(t.finish.bind(t));
}

function checkHome(assert, home) {
    return Q.resolve(home).then(function(home) {
        assert.strictEqual(home.id, "home");
        assert.strictEqual(typeof home.source, "string");
        assert.notEqual(home.source.indexOf("exports"), -1);
        assert.strictEqual(home.source.indexOf("install"), 0);
        return home;
    }).invoke("getRequiredP").then(function(reqs) {
        assert.strictEqual(reqs.length, 1);
        assert.strictEqual(reqs[0].id, "assert");
    });
}

exports.testModuleReader = function(t, assert) {
    var reader = new ModuleReader(debugContext, [getSourceP], []);
    var homeP = reader.readModuleP("home");
    checkHome(assert, homeP).done(t.finish.bind(t));
};

exports.testMissingModuleWarning = function(t, assert) {
    function helperP(context) {
        var reader = new ModuleReader(context, [getSourceP], []);
        var id = "this/module/should/not/exist";
        return reader.readModuleP(id).then(function(module) {
            assert.strictEqual(module.id, id);
            assert.notEqual(module.source.indexOf("throw new Error"), -1);
        });
    }

    waitForHelpers(t, helperP);
};

exports.testSkipFailingResolvers = function(t, assert) {
    var reader = new ModuleReader(debugContext, [function(id) {
        return this.makePromise(function(callback) {
            process.nextTick(function() {
                callback(new Error("bad thing happen"));
            });
        });
    }, function(id) {
        throw new Error("superbad situation");
    }, getSourceP], []);

    var homeP = reader.readModuleP("home");
    checkHome(assert, homeP).done(t.finish.bind(t));
};

exports.testReaderCaching = function(t, assert) {
    var reader = new ModuleReader(debugContext, [getSourceP], []);

    var homes = [
        reader.readModuleP("home"),
        reader.readModuleP("home"),
        reader.readModuleP.originalFn.call(reader, "home")
    ];

    assert.strictEqual(homes[0], homes[1]);
    assert.notStrictEqual(homes[0], homes[2]);
    assert.notStrictEqual(homes[1], homes[2]);

    Q.all(homes).spread(function(h0, h1, h2) {
        assert.strictEqual(h0, h1);
        assert.strictEqual(h0, h2);
        assert.strictEqual(h1, h2);

        assert.strictEqual(h0.hash, h1.hash);
        assert.strictEqual(h1.hash, h2.hash);
    }).done(t.finish.bind(t));
};

function makePipeline(context) {
    var reader = new ModuleReader(context, [getSourceP], []);
    var writer = new BundleWriter(context, []);
    return new Pipeline(context, reader, writer);
}

exports.testSimpleSchema = function(t, assert) {
    function helperP(context) {
        return makePipeline(context).setSchema({
            home: {}
        }).getTreeP().then(function(tree) {
            assert.ok(tree.home);
            assert.ok(tree.home.file);
            assert.ok(/\.js$/.test(tree.home.file));
        });
    }

    waitForHelpers(t, helperP);
};

function checkTree(assert, schema, tree) {
    var aks = Object.keys(schema);
    assert.deepEqual(aks, Object.keys(tree));

    aks.forEach(function(id) {
        var sVal = schema[id];
        var tVal = tree[id];
        assert.ok(tVal.file);
        if (tVal.then) {
            checkTree(assert, sVal, tVal.then);
        } else {
            assert.deepEqual(sVal, {});
        }
    });
}

exports.testComplexSchema = function(t, assert) {
    var schema = {
        "core": {
            "login": {
                "tests/login": {}
            },
            "home": {
                "tests/home": {}
            },
            "settings": {
                "tests/settings": {}
            }
        }
    };

    function helperP(context) {
        var pipeline = makePipeline(context).setSchema(schema);
        return pipeline.getTreeP().then(function(tree) {
            checkTree(assert, schema, tree);
        });
    }

    waitForHelpers(t, helperP);
};

exports.testSchemaWithEmptyBundles = function(t, assert) {
    var schema = {
        "core": {
            "home": {
                "assert": {
                    "settings": {}
                }
            },
            "assert": {
                "home": {}
            }
        }
    };

    function assertNotEmpty(entry) {
        assert.ok(entry);
        assert.strictEqual(typeof entry.empty, "undefined");
    }

    function assertEmpty(entry) {
        assert.ok(entry);
        assert.strictEqual(entry.empty, true);
    }

    function helperP(context) {
        var pipeline = makePipeline(context).setSchema(schema);

        return pipeline.getTreeP().then(function(tree) {
            assertNotEmpty(tree.core);
            assertNotEmpty(tree.core.then.home);
            assertEmpty(tree.core.then.home.then.assert);
            assertNotEmpty(tree.core.then.home.then.assert.then.settings);
            assertNotEmpty(tree.core.then.assert);
            assertNotEmpty(tree.core.then.assert.then.home);
            checkTree(assert, schema, tree);
        });
    }

    waitForHelpers(t, helperP);
};

exports.testRootArraySchemaSyntax = function(t, assert) {
    var rootsFile = path.join(sourceDir, "roots.json");
    var rootsP = util.readJsonFileP(rootsFile);

    function deepKeys(tree) {
        if (typeof tree !== "object")
            return [];

        var keys = Object.keys(tree);

        keys.forEach(function(key) {
            keys.push.apply(keys, deepKeys(tree[key].then));
        });

        return keys;
    }

    function uniq(list) {
        var seen = {};
        var result = [];
        list.forEach(function(str) {
            if (seen[str] !== true) {
                seen[str] = true;
                result.push(str);
            }
        });
        return result;
    }

    function helperP(context) {
        return rootsP.then(function(roots) {
            var pipeline = makePipeline(context).setSchema(roots);
            return pipeline.getTreeP().then(function(tree) {
                var keys = deepKeys(tree);
                var sortedRoots = roots.slice(0).sort();
                assert.ok(keys.length > sortedRoots.length);
                assert.strictEqual(keys.length, Math.pow(2, roots.length) - 1);
                assert.deepEqual(Object.keys(tree).sort(), sortedRoots);
                assert.deepEqual(uniq(keys).sort(), sortedRoots);
            });
        });
    }

    waitForHelpers(t, helperP);
};

exports.testBundle = function(t, assert) {
    function helperP(context) {
        var reader = new ModuleReader(context, [getSourceP], []);

        return reader.readModuleP("home").then(function(homeModule) {
            return makeBundleP(homeModule);
        }).then(function(bundle) {
            var homeModule = bundle.get("home");
            var assertModule = bundle.get("assert");
            assert.ok(homeModule);
            assert.ok(assertModule);
            assert.strictEqual(homeModule.id, "home");
            assert.strictEqual(assertModule.id, "assert");
        });
    }

    waitForHelpers(t, helperP);
};

function writeAndCheckExistsP(writer, bundleP) {
    var deferred = Q.defer();
    writer.writeBundleP(bundleP).then(function(fileName) {
        var filePath = path.join(outputDir, fileName);
        fs.exists(filePath, function(exists) {
            deferred.resolve(exists);
        });
    });
    return deferred.promise;
}

function clearOutputSync(outputDir) {
    fs.readdirSync(outputDir).forEach(function(file) {
        fs.unlinkSync(path.join(outputDir, file));
    });

    fs.rmdirSync(outputDir);
    fs.mkdirSync(outputDir);
}

exports.testBundleWriter = function(t, assert) {
    function helperP(context) {
        var reader = new ModuleReader(context, [getSourceP], []);
        var writer = new BundleWriter(context, []);

        return reader.readModuleP("home").then(function(home) {
            assert.strictEqual(home.id, "home");
            return writeAndCheckExistsP(writer, makeBundleP(home));
        }).then(function(exists) {
            assert.strictEqual(exists, true);
        });
    }

    waitForHelpers(t, helperP);
};

exports.testGrepP = function(t, assert) {
    Q.all([
        watcher.grepP("@providesModule\\s+\\S+"),
        debugContext.getProvidedP()
    ]).spread(function(pathToMatch, valueToPath) {
        assert.deepEqual(pathToMatch, {
            "widget/share.js": "@providesModule WidgetShare"
        });
        assert.deepEqual(valueToPath, {
            "WidgetShare": "widget/share.js"
        });
    }).done(t.finish.bind(t));
};

exports.testMakePromise = function(t, assert) {
    var error = new Error("test");

    function helperP(context) {
        return context.makePromise(function(callback) {
            process.nextTick(function() {
                callback(error, "asdf");
            });
        }).then(function() {
            assert.ok(false, "should have thrown an error");
        }, function(err) {
            assert.strictEqual(err, error);

            return context.makePromise(function(callback) {
                process.nextTick(function() {
                    callback(null, "success");
                });
            }).then(function(result) {
                assert.strictEqual(result, "success");
            });
        })
    }

    waitForHelpers(t, helperP);
};
<commit_msg>Remove Brigade tests that are no longer applicable.<commit_after>var Watcher = require("../lib/watcher").Watcher;
var BuildContext = require("../lib/context").BuildContext;
var ModuleReader = require("../lib/reader").ModuleReader;
var util = require("../lib/util");
var fs = require("fs");
var Q = require("q");

var path = require("path");
var sourceDir = path.resolve(__dirname, "source");
var outputDir = path.resolve(__dirname, "output");

try {
    fs.mkdirSync(outputDir);
} catch (exists) {
    // pass
}

var watcher = new Watcher(sourceDir);

var debugContext = new BuildContext({
    debug: true
}, watcher, outputDir, []);

var releaseContext = new BuildContext({
    debug: false
}, watcher, outputDir, []);

function getSourceP(id) {
    return this.readFileP(id + ".js");
}

function waitForHelpers(t, helperP) {
    Q.all([
        helperP(debugContext),
        helperP(releaseContext)
    ]).done(t.finish.bind(t));
}

function checkHome(assert, home) {
    return Q.resolve(home).then(function(home) {
        assert.strictEqual(home.id, "home");
        assert.strictEqual(typeof home.source, "string");
        assert.notEqual(home.source.indexOf("exports"), -1);
        assert.strictEqual(home.source.indexOf('require("assert");'), 0);
        return home;
    }).invoke("getRequiredP").then(function(reqs) {
        assert.strictEqual(reqs.length, 1);
        assert.strictEqual(reqs[0].id, "assert");
    });
}

exports.testModuleReader = function(t, assert) {
    var reader = new ModuleReader(debugContext, [getSourceP], []);
    var homeP = reader.readModuleP("home");
    checkHome(assert, homeP).done(t.finish.bind(t));
};

exports.testMissingModuleWarning = function(t, assert) {
    function helperP(context) {
        var reader = new ModuleReader(context, [getSourceP], []);
        var id = "this/module/should/not/exist";
        return reader.readModuleP(id).then(function(module) {
            assert.strictEqual(module.id, id);
            assert.notEqual(module.source.indexOf("throw new Error"), -1);
        });
    }

    waitForHelpers(t, helperP);
};

exports.testSkipFailingResolvers = function(t, assert) {
    var reader = new ModuleReader(debugContext, [function(id) {
        return this.makePromise(function(callback) {
            process.nextTick(function() {
                callback(new Error("bad thing happen"));
            });
        });
    }, function(id) {
        throw new Error("superbad situation");
    }, getSourceP], []);

    var homeP = reader.readModuleP("home");
    checkHome(assert, homeP).done(t.finish.bind(t));
};

exports.testReaderCaching = function(t, assert) {
    var reader = new ModuleReader(debugContext, [getSourceP], []);

    var homes = [
        reader.readModuleP("home"),
        reader.readModuleP("home"),
        reader.readModuleP.originalFn.call(reader, "home")
    ];

    assert.strictEqual(homes[0], homes[1]);
    assert.notStrictEqual(homes[0], homes[2]);
    assert.notStrictEqual(homes[1], homes[2]);

    Q.all(homes).spread(function(h0, h1, h2) {
        assert.strictEqual(h0, h1);
        assert.strictEqual(h0, h2);
        assert.strictEqual(h1, h2);

        assert.strictEqual(h0.hash, h1.hash);
        assert.strictEqual(h1.hash, h2.hash);
    }).done(t.finish.bind(t));
};

exports.testGrepP = function(t, assert) {
    Q.all([
        watcher.grepP("@providesModule\\s+\\S+"),
        debugContext.getProvidedP()
    ]).spread(function(pathToMatch, valueToPath) {
        assert.deepEqual(pathToMatch, {
            "widget/share.js": "@providesModule WidgetShare"
        });
        assert.deepEqual(valueToPath, {
            "WidgetShare": "widget/share.js"
        });
    }).done(t.finish.bind(t));
};

exports.testMakePromise = function(t, assert) {
    var error = new Error("test");

    function helperP(context) {
        return context.makePromise(function(callback) {
            process.nextTick(function() {
                callback(error, "asdf");
            });
        }).then(function() {
            assert.ok(false, "should have thrown an error");
        }, function(err) {
            assert.strictEqual(err, error);

            return context.makePromise(function(callback) {
                process.nextTick(function() {
                    callback(null, "success");
                });
            }).then(function(result) {
                assert.strictEqual(result, "success");
            });
        })
    }

    waitForHelpers(t, helperP);
};
<|endoftext|>