<commit_before>;(function(){//IIFE

angular.module('brewKeeper')
      .controller('brewIt', function($scope, $http, $routeParams, $location, $route, $rootScope){
        $(document).scrollTop(0);
        var id = $routeParams.id;
        var username =$routeParams.username;
        $scope.username = $routeParams.username;
        $scope.showStars = false;

        $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/')
          .then(function(response){
            $scope.detail = response.data;
            $scope.steps = response.data.steps;
            $scope.notes = response.data.brewnotes;
            $scope.countdownVal = response.data.total_duration;
            $scope.ratings = [{
                max: 5
            }];
            var stepArray = [] //create an array of step #'s'
            for(step in $scope.steps){
              stepArray.push($scope.steps[step].step_number)
            };
            $scope.stepArray = stepArray;
            $scope.stepTotal = stepArray.length;
          });

        //load the data if the page is manually reset
        // window.onload = function(){
        //   $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + "/")
        //     .then(function(response){
        //       $rootScope.detail = response.data;
        //       $rootScope.steps = response.data.steps;
        //       $rootScope.notes = response.data.brewnotes;
        //       var stepArray = []; //create an array of step #'s'
        //       for(step in $rootScope.steps){
        //         stepArray.push($rootScope.steps[step].step_number)
        //       };
        //       $rootScope.stepArray = stepArray;
        //       $scope.stepTotal = stepArray.length;
        //       });
        //   $scope.resetBrew();
        // }

        var stepArray = [] //create an array of step #'s'
        for(step in $rootScope.steps){
          stepArray.push($rootScope.steps[step].step_number)
        };
        $rootScope.stepArray = stepArray;
        $scope.stepTotal = stepArray.length;

        var timerRunning = false //logic for brew timer
        //start brew function
        $scope.startBrew = function(brewCount){
          if(timerRunning){
            return;
          }
          $("."+$scope.stepArray[0]).removeClass("inactive-step").addClass("current-step");
          // $("div.delay").animate({height: 0}, 1000, function(){
            $("div.delay").addClass("hidden").addClass("inactive-step")
          // });
          $(".delay timer").addClass("hidden");
          $("timer."+$scope.stepArray[0]).removeClass("hidden");//Show's timer for active step
          $('timer')[1].start();
          timerRunning = true;
        };

        //runs when brew again button pushed
        $scope.reStartBrew = function(){
          if(timerRunning){
            return;
          }
          $(".countdown").removeClass("hidden");
          $("div.restart").addClass("hidden");
          $(".countdown").removeClass("hidden");
          $("timer.delay").removeClass("hidden");
          $(".step").addClass("inactive-step")
          $("a[href].restart-brew").addClass("hidden");
          $("a[href].add-brew-note").addClass("hidden");
          // $(".rating").addClass("hidden");
          $("a[href].reset-brew").removeClass("hidden");
          $('timer')[0].start();
          $scope.showStars = false;
        }

        // $scope.stopBrew = function(){
        //   console.log("pause button pressed");
        //   $scope.$broadcast('timer-stop');
        // }; //This can be used to pause process if needed.

        $scope.resetBrew = function(){

          $(".current-step").addClass("hidden")
          $("timer.counter").addClass("hidden");
          $(".delay.hidden").removeClass("hidden");
          $(".current-step").removeClass("current-step");
          $(".countdown").removeClass("hidden");

          $scope.$broadcast('timer-reset');
          $("a[href].restart-brew").removeClass("hidden");
          $("a[href].add-brew-note").removeClass("hidden");
          // $(".rating").removeClass("hidden");
          $("a[href].reset-brew").addClass("hidden");
          $scope.showStars = true;
          timerRunning = false;

          //getting the data again solves the timers not
          //resetting correctly
          $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/')
            .then(function(response){
              $scope.detail = response.data;
              $scope.steps = response.data.steps;
              $scope.notes = response.data.brewnotes;
              $scope.countdownVal = response.data.total_duration;
            })
        }; //end resetBrew

        // $scope.finishBrew = function(id){
        //   $scope.nextStep(id);
        //   $("."+id).removeClass("current-step");
        //   $("."+id).addClass("hidden")
        // };
        $scope.nextStep = function(stepNumber, brewCount){
          var nextStepIndex = $scope.stepArray.indexOf(stepNumber) + 1;
          var nextStep = $scope.stepArray[nextStepIndex];
          var prevStep = $scope.stepArray[nextStepIndex - 2]
          var nextTimerId = $scope.stepArray.indexOf(stepNumber) + 2;
          if(nextStepIndex >= $scope.steps.length){
            //end of brew countdown
            $scope.resetBrew();
            //update brew_count
            var recipe = {};
            recipe.brew_count = brewCount + 1;
            // brewCount++; //increment brew counter
            $http.patch('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/', recipe);
            return
          }
          $("timer."+stepNumber).addClass("hidden");// Hide last step
          $("."+stepNumber).slideUp(1000).addClass("finished");// Hide last step
//Change next step to green  and grow next step to 200
          $("timer."+nextStep).removeClass("hidden");
          $("."+nextStep).addClass("current-step").removeClass("inactive-step");

          $('timer')[nextTimerId].start();
        }; //end nextStep function

      $scope.brewnote = { }
      $scope.addBrewNote=function(){
        $http.post('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/brewnotes/', $scope.brewnote)
        .success(function (data) {
          var id = data.id
        })
      $scope.brewnote = { };
      }//Add Brew Note Form

      $(".add-brew-note").on('click', function() {
        $(".brew-form").toggleClass("hidden");
      })
      $(".save-note").on('click', function() {
        $(".brew-form").addClass("hidden");
      });//Add hidden class to brewNote form on submit
      $(".cancel-note").on('click', function() {
        $(".brew-form").addClass("hidden");
      });//Cancel BrewNote form

      $scope.rateRecipe = function (rating, id) {
        var newRating = {"rating": rating}
        $http.patch("https://brew-keeper-api.herokuapp.com/api/users/"+ username + "/recipes/"+ id + "/", newRating)
      }

    }) //end brewit controller
})();//END Angular IIFE
<commit_msg>hide brew-note form when brew-it restarts<commit_after>;(function(){//IIFE

angular.module('brewKeeper')
      .controller('brewIt', function($scope, $http, $routeParams, $location, $route, $rootScope){
        $(document).scrollTop(0);
        var id = $routeParams.id;
        var username =$routeParams.username;
        $scope.username = $routeParams.username;
        $scope.showStars = false;

        $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/')
          .then(function(response){
            $scope.detail = response.data;
            $scope.steps = response.data.steps;
            $scope.notes = response.data.brewnotes;
            $scope.countdownVal = response.data.total_duration;
            $scope.ratings = [{
                max: 5
            }];
            var stepArray = [] //create an array of step #'s'
            for(step in $scope.steps){
              stepArray.push($scope.steps[step].step_number)
            };
            $scope.stepArray = stepArray;
            $scope.stepTotal = stepArray.length;
          });

        //load the data if the page is manually reset
        // window.onload = function(){
        //   $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + "/")
        //     .then(function(response){
        //       $rootScope.detail = response.data;
        //       $rootScope.steps = response.data.steps;
        //       $rootScope.notes = response.data.brewnotes;
        //       var stepArray = []; //create an array of step #'s'
        //       for(step in $rootScope.steps){
        //         stepArray.push($rootScope.steps[step].step_number)
        //       };
        //       $rootScope.stepArray = stepArray;
        //       $scope.stepTotal = stepArray.length;
        //       });
        //   $scope.resetBrew();
        // }

        var stepArray = [] //create an array of step #'s'
        for(step in $rootScope.steps){
          stepArray.push($rootScope.steps[step].step_number)
        };
        $rootScope.stepArray = stepArray;
        $scope.stepTotal = stepArray.length;

        var timerRunning = false //logic for brew timer
        //start brew function
        $scope.startBrew = function(brewCount){
          if(timerRunning){
            return;
          }
          $("."+$scope.stepArray[0]).removeClass("inactive-step").addClass("current-step");
          // $("div.delay").animate({height: 0}, 1000, function(){
            $("div.delay").addClass("hidden").addClass("inactive-step")
          // });
          $(".delay timer").addClass("hidden");
          $("timer."+$scope.stepArray[0]).removeClass("hidden");//Show's timer for active step
          $('timer')[1].start();
          timerRunning = true;
        };

        //runs when brew again button pushed
        $scope.reStartBrew = function(){
          if(timerRunning){
            return;
          }
          $(".countdown").removeClass("hidden");
          $(".brew-form").addClass("hidden");
          $("div.restart").addClass("hidden");
          $(".countdown").removeClass("hidden");
          $("timer.delay").removeClass("hidden");
          $(".step").addClass("inactive-step")
          $("a[href].restart-brew").addClass("hidden");
          $("a[href].add-brew-note").addClass("hidden");
          // $(".rating").addClass("hidden");
          $("a[href].reset-brew").removeClass("hidden");
          $('timer')[0].start();
          $scope.showStars = false;
        }

        // $scope.stopBrew = function(){
        //   console.log("pause button pressed");
        //   $scope.$broadcast('timer-stop');
        // }; //This can be used to pause process if needed.

        $scope.resetBrew = function(){

          $(".current-step").addClass("hidden")
          $("timer.counter").addClass("hidden");
          $(".delay.hidden").removeClass("hidden");
          $(".current-step").removeClass("current-step");
          $(".countdown").removeClass("hidden");

          $scope.$broadcast('timer-reset');
          $("a[href].restart-brew").removeClass("hidden");
          $("a[href].add-brew-note").removeClass("hidden");
          // $(".rating").removeClass("hidden");
          $("a[href].reset-brew").addClass("hidden");
          $scope.showStars = true;
          timerRunning = false;

          //getting the data again solves the timers not
          //resetting correctly
          $http.get('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/')
            .then(function(response){
              $scope.detail = response.data;
              $scope.steps = response.data.steps;
              $scope.notes = response.data.brewnotes;
              $scope.countdownVal = response.data.total_duration;
            })
        }; //end resetBrew

        // $scope.finishBrew = function(id){
        //   $scope.nextStep(id);
        //   $("."+id).removeClass("current-step");
        //   $("."+id).addClass("hidden")
        // };
        $scope.nextStep = function(stepNumber, brewCount){
          var nextStepIndex = $scope.stepArray.indexOf(stepNumber) + 1;
          var nextStep = $scope.stepArray[nextStepIndex];
          var prevStep = $scope.stepArray[nextStepIndex - 2]
          var nextTimerId = $scope.stepArray.indexOf(stepNumber) + 2;
          if(nextStepIndex >= $scope.steps.length){
            //end of brew countdown
            $scope.resetBrew();
            //update brew_count
            var recipe = {};
            recipe.brew_count = brewCount + 1;
            // brewCount++; //increment brew counter
            $http.patch('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/', recipe);
            return
          }
          $("timer."+stepNumber).addClass("hidden");// Hide last step
          $("."+stepNumber).slideUp(1000).addClass("finished");// Hide last step
//Change next step to green  and grow next step to 200
          $("timer."+nextStep).removeClass("hidden");
          $("."+nextStep).addClass("current-step").removeClass("inactive-step");

          $('timer')[nextTimerId].start();
        }; //end nextStep function

      $scope.brewnote = { }
      $scope.addBrewNote=function(){
        $http.post('https://brew-keeper-api.herokuapp.com/api/users/' + username + '/recipes/' + id + '/brewnotes/', $scope.brewnote)
        .success(function (data) {
          var id = data.id
        })
      $scope.brewnote = { };
      }//Add Brew Note Form

      $(".add-brew-note").on('click', function() {
        $(".brew-form").toggleClass("hidden");
      })
      $(".save-note").on('click', function() {
        $(".brew-form").addClass("hidden");
      });//Add hidden class to brewNote form on submit
      $(".cancel-note").on('click', function() {
        $(".brew-form").addClass("hidden");
      });//Cancel BrewNote form

      $scope.rateRecipe = function (rating, id) {
        var newRating = {"rating": rating}
        $http.patch("https://brew-keeper-api.herokuapp.com/api/users/"+ username + "/recipes/"+ id + "/", newRating)
      }

    }) //end brewit controller
})();//END Angular IIFE
<|endoftext|>


<commit_before>$(function(){

  var RESTART_DELAY = 1000;
  var UPDATE_SCHEDULE_DELAY = 15 * 60 * 1000; //check for updated schedule every 15 minutes
  var CHECK_SCHEDULE_DELAY = 30 * 1000; //check content against schedule every 30 seconds

  var restarting = false;
  var reset = false;
  var win = window;
  var activeTimeout;
  var restart;
  var schedule,scheduleURL,defaultURL,currentURL,updateScheduleTimeout,checkScheduleTimeout;

  function updateSchedule(){
    $.getJSON(scheduleURL, function(s) {
      if(s && s.schedule && s.schedule.Value && s.schedule.Value.items && s.schedule.Value.items.length){
        var s = s.schedule.Value.items;
        for(var i = 0; i < s.length; i++){
          if(s[i].content && s[i].start && s[i].end){
            s[i].start = new Date(Date.parse(s[i].start));
            s[i].end = new Date(Date.parse(s[i].end));
            s[i].duration = (s[i].end - s[i].start) / 1000; //duration is in seconds
          }else{
            //item did not include start, end, or content: invalid
            s = s.splice(i--, 1);
          }
        }
        schedule = s;
        checkSchedule();
      }
    });
  }

  function checkSchedule(){
    var s = schedule;
    if(s && s.length){
      var now = Date.now();
      var hasScheduledContent = false;
      for(var i = 0; i < s.length; i++){
        if(now >= s[i].start && now < s[i].end){
          hasScheduledContent = true;
          if(s[i].content != currentURL){
            currentURL = s[i].content;
            $("#browser").remove();
            loadContent(currentURL);
          }
        }
        if(!hasScheduledContent && currentURL != defaultURL){
          currentURL = defaultURL;
          $("#browser").remove();
          loadContent(currentURL);
        }
      }
    }
  }

  chrome.storage.local.get(null,function(data){

     if(data.local){
       $(document).keydown(function(e) {
         if(e.which == 65 && e.ctrlKey)
           $('#login').openModal();
       });

       $('#submit').click(function(e){
         e.preventDefault();
         var username = $('#username').val();
         var password = $("#password").val();
         if(username == data.username && password == data.password){
           $('#login').closeModal();
           $('#username').val('');
           $("#password").val('');
           openWindow("windows/setup.html");
        }else{
          Materialize.toast('Invalid login.', 4000);
        }
       });
     }

     if(data.restart && parseInt(data.restart)){
       var hour = parseInt(data.restart) - 1;
       var now = moment();
       restart = moment();
       restart.hour(hour).set({'minute':0, 'second':0, 'millisecond':0});
       if(now.isAfter(restart)) restart.add(1,'d'); //if we're past the time today, do it tomorrow
       setInterval(function(){
          var now = moment();
          if(now.isAfter(restart)) chrome.runtime.reload();
        },60*1000);
     }

     if(data.remoteschedule && data.remotescheduleurl){
       scheduleURL = data.remotescheduleurl;
       updateSchedule();
       setInterval(updateSchedule,UPDATE_SCHEDULE_DELAY);
       setInterval(checkSchedule,CHECK_SCHEDULE_DELAY);
     }

     reset = data.reset && parseFloat(data.reset) > 0 ? parseFloat(data.reset) : false;

     active();

     $('*').on('click mousedown mouseup mousemove touch touchstart touchend keypress keydown',active);

     currentURL = defaultURL = data.url;
     loadContent(currentURL);

  });

  chrome.runtime.onMessage.addListener(function(data){
    if(data.url && data.url != $("#browser").attr('src')){
      $("#browser").attr('src',data.url);
    }
  });

  function active(){
    if(reset){
      if(activeTimeout) clearTimeout(activeTimeout);
      activeTimeout = setTimeout(function(){
        $("#browser").remove();
        loadContent(currentURL);
      },reset*60*1000);
    }
  }

  function loadContent(url){
    $('<webview id="browser"/>')
     .css({
       width:'100%',
       height:'100%',
       position:'absolute',
       top:0,
       left:0,
       right:0,
       bottom:0
     })
     .attr('partition','persistant:kiosk')
     .on('exit',onEnded)
     .on('unresponsive',onEnded)
     .on('loadabort',function(e){if(e.isTopLevel) onEnded(e); })
     .on('consolemessage',function(e){
       if(e.originalEvent.message == 'kiosk:active') active();
     })
     .on('permissionrequest',function(e){
       if(e.originalEvent.permission === 'media') {
         e.preventDefault();
         chrome.permissions.contains({
           permissions: ['audioCapture','videoCapture']
         }, function(result) {
           if (result) {
             // The app has the permissions.
             e.originalEvent.request.allow();
           } else {
             // The app doesn't have the permissions.
             // request it
             $('#mediaPermission .ok').click(function(){
               chrome.permissions.request({
                 permissions: ['audioCapture','videoCapture']
               },function(granted){
                 if(granted) e.originalEvent.request.allow();
               });
             });
             $('#mediaPermission').openModal();
           }
         });
       }
     })
     .attr('src',url)
     .prependTo('body');
  }

  function onEnded(event){
    if(!restarting){
      restarting = true;
      $("#browser").remove();
      setTimeout(function(){
        loadContent(data.url);
        restarting = false;
      },RESTART_DELAY);
   }
  }

  function openWindow(path){
    chrome.system.display.getInfo(function(d){
      chrome.app.window.create(path, {
        'frame': 'none',
        'id': 'setup',
        'state': 'fullscreen',
        'bounds':{
           'left':0,
           'top':0,
           'width':d[0].bounds.width,
           'height':d[0].bounds.height
        }
      },function(w){
        chrome.app.window.current().close();
        win = w;
        win.fullscreen();
        setTimeout(function(){
          win.fullscreen();
        },1000);
      });
    });
  }

});
<commit_msg>additional bug fixes and schedule format support<commit_after>$(function(){

  var RESTART_DELAY = 1000;
  var UPDATE_SCHEDULE_DELAY = 15 * 60 * 1000; //check for updated schedule every 15 minutes
  var CHECK_SCHEDULE_DELAY = 30 * 1000; //check content against schedule every 30 seconds

  var restarting = false;
  var reset = false;
  var win = window;
  var activeTimeout;
  var restart;
  var schedule,scheduleURL,defaultURL,currentURL,updateScheduleTimeout,checkScheduleTimeout;

  function updateSchedule(){
    $.getJSON(scheduleURL, function(s) {
      if(s && s.schedule && s.schedule.Value && s.schedule.Value.length){
        //support schedule.Value as structure or array containing structure
        s.schedule.Value = s.schedule.Value[0];
      }
      if(s && s.schedule && s.schedule.Value && s.schedule.Value.items && s.schedule.Value.items.length){
        var s = s.schedule.Value.items;
        for(var i = 0; i < s.length; i++){
          if(s[i].content && s[i].start && s[i].end){
            s[i].start = new Date(Date.parse(s[i].start));
            s[i].end = new Date(Date.parse(s[i].end));
            s[i].duration = (s[i].end - s[i].start) / 1000; //duration is in seconds
          }else{
            //item did not include start, end, or content: invalid
            s = s.splice(i--, 1);
          }
        }
        schedule = s;
        checkSchedule();
      }
    });
  }

  function checkSchedule(){
    var s = schedule;
    if(s && s.length){
      var now = Date.now();
      var hasScheduledContent = false;
      for(var i = 0; i < s.length; i++){
        if(now >= s[i].start && now < s[i].end){
          hasScheduledContent = true;
          if(s[i].content != currentURL){
            currentURL = s[i].content;
            $("#browser").remove();
            loadContent(currentURL);
          }
        }
      }
      if(!hasScheduledContent && currentURL != defaultURL){
        currentURL = defaultURL;
        $("#browser").remove();
        loadContent(currentURL);
      }
    }
  }

  chrome.storage.local.get(null,function(data){

     if(data.local){
       $(document).keydown(function(e) {
         if(e.which == 65 && e.ctrlKey)
           $('#login').openModal();
       });

       $('#submit').click(function(e){
         e.preventDefault();
         var username = $('#username').val();
         var password = $("#password").val();
         if(username == data.username && password == data.password){
           $('#login').closeModal();
           $('#username').val('');
           $("#password").val('');
           openWindow("windows/setup.html");
        }else{
          Materialize.toast('Invalid login.', 4000);
        }
       });
     }

     if(data.restart && parseInt(data.restart)){
       var hour = parseInt(data.restart) - 1;
       var now = moment();
       restart = moment();
       restart.hour(hour).set({'minute':0, 'second':0, 'millisecond':0});
       if(now.isAfter(restart)) restart.add(1,'d'); //if we're past the time today, do it tomorrow
       setInterval(function(){
          var now = moment();
          if(now.isAfter(restart)) chrome.runtime.reload();
        },60*1000);
     }

     if(data.remoteschedule && data.remotescheduleurl){
       scheduleURL = data.remotescheduleurl;
       updateSchedule();
       setInterval(updateSchedule,UPDATE_SCHEDULE_DELAY);
       setInterval(checkSchedule,CHECK_SCHEDULE_DELAY);
     }

     reset = data.reset && parseFloat(data.reset) > 0 ? parseFloat(data.reset) : false;

     active();

     $('*').on('click mousedown mouseup mousemove touch touchstart touchend keypress keydown',active);

     currentURL = defaultURL = data.url;
     loadContent(currentURL);

  });

  chrome.runtime.onMessage.addListener(function(data){
    if(data.url && data.url != $("#browser").attr('src')){
      $("#browser").attr('src',data.url);
    }
  });

  function active(){
    if(reset){
      if(activeTimeout) clearTimeout(activeTimeout);
      activeTimeout = setTimeout(function(){
        $("#browser").remove();
        loadContent(currentURL);
      },reset*60*1000);
    }
  }

  function loadContent(url){
    $('<webview id="browser"/>')
     .css({
       width:'100%',
       height:'100%',
       position:'absolute',
       top:0,
       left:0,
       right:0,
       bottom:0
     })
     .attr('partition','persistant:kiosk')
     .on('exit',onEnded)
     .on('unresponsive',onEnded)
     .on('loadabort',function(e){if(e.isTopLevel) onEnded(e); })
     .on('consolemessage',function(e){
       if(e.originalEvent.message == 'kiosk:active') active();
     })
     .on('permissionrequest',function(e){
       if(e.originalEvent.permission === 'media') {
         e.preventDefault();
         chrome.permissions.contains({
           permissions: ['audioCapture','videoCapture']
         }, function(result) {
           if (result) {
             // The app has the permissions.
             e.originalEvent.request.allow();
           } else {
             // The app doesn't have the permissions.
             // request it
             $('#mediaPermission .ok').click(function(){
               chrome.permissions.request({
                 permissions: ['audioCapture','videoCapture']
               },function(granted){
                 if(granted) e.originalEvent.request.allow();
               });
             });
             $('#mediaPermission').openModal();
           }
         });
       }
     })
     .attr('src',url)
     .prependTo('body');
  }

  function onEnded(event){
    if(!restarting){
      restarting = true;
      $("#browser").remove();
      setTimeout(function(){
        loadContent(data.url);
        restarting = false;
      },RESTART_DELAY);
   }
  }

  function openWindow(path){
    chrome.system.display.getInfo(function(d){
      chrome.app.window.create(path, {
        'frame': 'none',
        'id': 'setup',
        'state': 'fullscreen',
        'bounds':{
           'left':0,
           'top':0,
           'width':d[0].bounds.width,
           'height':d[0].bounds.height
        }
      },function(w){
        chrome.app.window.current().close();
        win = w;
        win.fullscreen();
        setTimeout(function(){
          win.fullscreen();
        },1000);
      });
    });
  }

});
<|endoftext|>


<commit_before>    /**
     * Confirm dialog object
     *
     *	alertify.confirm(message);
     *	alertify.confirm(message, onok);
     *	alertify.confirm(message, onok, oncancel);
     *	alertify.confirm(title, message, onok, oncancel);
     */
    alertify.dialog('confirm', function () {

        var autoConfirm = {
            timer: null,
            index: null,
            text: null,
            duratuin: null,
            task: function (event, self) {
                if (self.isOpen()) {
                    self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (' + autoConfirm.duration + ') ';
                    autoConfirm.duration -= 1;
                    if (autoConfirm.duration === -1) {
                        clearAutoConfirm(self);
                        var button = self.__internal.buttons[autoConfirm.index];
                        var closeEvent = createCloseEvent(autoConfirm.index, button);

                        if (typeof self.callback === 'function') {
                            self.callback.apply(self, [closeEvent]);
                        }
                        //close the dialog.
                        if (closeEvent.close !== false) {
                            self.close();
                        }
                    }
                } else {
                    clearAutoConfirm(self);
                }
            }
        };

        function clearAutoConfirm(self) {
            if (autoConfirm.timer !== null) {
                clearInterval(autoConfirm.timer);
                autoConfirm.timer = null;
                self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text;
            }
        }

        function startAutoConfirm(self, index, duration) {
            clearAutoConfirm(self);
            autoConfirm.duration = duration;
            autoConfirm.index = index;
            autoConfirm.text = self.__internal.buttons[index].element.innerHTML;
            autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000);
            autoConfirm.task(null, self);
        }

        return {
            main: function (_title, _message, _onok, _oncancel) {
                var title, message, onok, oncancel;
                switch (arguments.length) {
                case 1:
                    message = _title;
                    break;
                case 2:
                    message = _title;
                    onok = _message;
                    break;
                case 3:
                    message = _title;
                    onok = _message;
                    oncancel = _onok;
                    break;
                case 4:
                    title = _title;
                    message = _message;
                    onok = _onok;
                    oncancel = _oncancel;
                    break;
                }
                this.set('title', title);
                this.set('message', message);
                this.set('onok', onok);
                this.set('oncancel', oncancel);
                return this;
            },
            setup: function () {
                return {
                    buttons: [
                        {
                            text: alertify.defaults.glossary.ok,
                            key: keys.ENTER,
                            className: alertify.defaults.theme.ok,
                        },
                        {
                            text: alertify.defaults.glossary.cancel,
                            key: keys.ESC,
                            invokeOnClose: true,
                            className: alertify.defaults.theme.cancel,
                        }
                    ],
                    focus: {
                        element: 0,
                        select: false
                    },
                    options: {
                        maximizable: false,
                        resizable: false
                    }
                };
            },
            build: function () {
                //nothing
            },
            prepare: function () {
                //nothing
            },
            setMessage: function (message) {
                this.setContent(message);
            },
            settings: {
                message: null,
                labels: null,
                onok: null,
                oncancel: null,
                defaultFocus: null,
                reverseButtons: null,
            },
            settingUpdated: function (key, oldValue, newValue) {
                switch (key) {
                case 'message':
                    this.setMessage(newValue);
                    break;
                case 'labels':
                    if ('ok' in newValue && this.__internal.buttons[0].element) {
                        this.__internal.buttons[0].text = newValue.ok;
                        this.__internal.buttons[0].element.innerHTML = newValue.ok;
                    }
                    if ('cancel' in newValue && this.__internal.buttons[1].element) {
                        this.__internal.buttons[1].text = newValue.cancel;
                        this.__internal.buttons[1].element.innerHTML = newValue.cancel;
                    }
                    break;
                case 'reverseButtons':
                    if (newValue === true) {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
                    } else {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
                    }
                    break;
                case 'defaultFocus':
                    this.__internal.focus.element = newValue === 'ok' ? 0 : 1;
                    break;
                }
            },
            callback: function (closeEvent) {
                clearAutoConfirm(this);
                var returnValue;
                switch (closeEvent.index) {
                case 0:
                    if (typeof this.get('onok') === 'function') {
                        returnValue = this.get('onok').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                case 1:
                    if (typeof this.get('oncancel') === 'function') {
                        returnValue = this.get('oncancel').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                }
            },
            autoOk: function (duration) {
                startAutoConfirm(this, 0, duration);
                return this;
            },
            autoCancel: function (duration) {
                startAutoConfirm(this, 1, duration);
                return this;
            }
        };
    });<commit_msg>fix typo<commit_after>    /**
     * Confirm dialog object
     *
     *	alertify.confirm(message);
     *	alertify.confirm(message, onok);
     *	alertify.confirm(message, onok, oncancel);
     *	alertify.confirm(title, message, onok, oncancel);
     */
    alertify.dialog('confirm', function () {

        var autoConfirm = {
            timer: null,
            index: null,
            text: null,
            duration: null,
            task: function (event, self) {
                if (self.isOpen()) {
                    self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (' + autoConfirm.duration + ') ';
                    autoConfirm.duration -= 1;
                    if (autoConfirm.duration === -1) {
                        clearAutoConfirm(self);
                        var button = self.__internal.buttons[autoConfirm.index];
                        var closeEvent = createCloseEvent(autoConfirm.index, button);

                        if (typeof self.callback === 'function') {
                            self.callback.apply(self, [closeEvent]);
                        }
                        //close the dialog.
                        if (closeEvent.close !== false) {
                            self.close();
                        }
                    }
                } else {
                    clearAutoConfirm(self);
                }
            }
        };

        function clearAutoConfirm(self) {
            if (autoConfirm.timer !== null) {
                clearInterval(autoConfirm.timer);
                autoConfirm.timer = null;
                self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text;
            }
        }

        function startAutoConfirm(self, index, duration) {
            clearAutoConfirm(self);
            autoConfirm.duration = duration;
            autoConfirm.index = index;
            autoConfirm.text = self.__internal.buttons[index].element.innerHTML;
            autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000);
            autoConfirm.task(null, self);
        }

        return {
            main: function (_title, _message, _onok, _oncancel) {
                var title, message, onok, oncancel;
                switch (arguments.length) {
                case 1:
                    message = _title;
                    break;
                case 2:
                    message = _title;
                    onok = _message;
                    break;
                case 3:
                    message = _title;
                    onok = _message;
                    oncancel = _onok;
                    break;
                case 4:
                    title = _title;
                    message = _message;
                    onok = _onok;
                    oncancel = _oncancel;
                    break;
                }
                this.set('title', title);
                this.set('message', message);
                this.set('onok', onok);
                this.set('oncancel', oncancel);
                return this;
            },
            setup: function () {
                return {
                    buttons: [
                        {
                            text: alertify.defaults.glossary.ok,
                            key: keys.ENTER,
                            className: alertify.defaults.theme.ok,
                        },
                        {
                            text: alertify.defaults.glossary.cancel,
                            key: keys.ESC,
                            invokeOnClose: true,
                            className: alertify.defaults.theme.cancel,
                        }
                    ],
                    focus: {
                        element: 0,
                        select: false
                    },
                    options: {
                        maximizable: false,
                        resizable: false
                    }
                };
            },
            build: function () {
                //nothing
            },
            prepare: function () {
                //nothing
            },
            setMessage: function (message) {
                this.setContent(message);
            },
            settings: {
                message: null,
                labels: null,
                onok: null,
                oncancel: null,
                defaultFocus: null,
                reverseButtons: null,
            },
            settingUpdated: function (key, oldValue, newValue) {
                switch (key) {
                case 'message':
                    this.setMessage(newValue);
                    break;
                case 'labels':
                    if ('ok' in newValue && this.__internal.buttons[0].element) {
                        this.__internal.buttons[0].text = newValue.ok;
                        this.__internal.buttons[0].element.innerHTML = newValue.ok;
                    }
                    if ('cancel' in newValue && this.__internal.buttons[1].element) {
                        this.__internal.buttons[1].text = newValue.cancel;
                        this.__internal.buttons[1].element.innerHTML = newValue.cancel;
                    }
                    break;
                case 'reverseButtons':
                    if (newValue === true) {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
                    } else {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
                    }
                    break;
                case 'defaultFocus':
                    this.__internal.focus.element = newValue === 'ok' ? 0 : 1;
                    break;
                }
            },
            callback: function (closeEvent) {
                clearAutoConfirm(this);
                var returnValue;
                switch (closeEvent.index) {
                case 0:
                    if (typeof this.get('onok') === 'function') {
                        returnValue = this.get('onok').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                case 1:
                    if (typeof this.get('oncancel') === 'function') {
                        returnValue = this.get('oncancel').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                }
            },
            autoOk: function (duration) {
                startAutoConfirm(this, 0, duration);
                return this;
            },
            autoCancel: function (duration) {
                startAutoConfirm(this, 1, duration);
                return this;
            }
        };
    });<|endoftext|>


<commit_before>/* global navigator, window, document, chrome, location, history, top */

let collapsers, jsonObject, jsonSelector, selectedLI;
chrome.runtime.onMessage.addListener(message => {
	if (message.copy) {
		copy(message.value);
	}
});
if (document.body && (document.body.childNodes[0] && document.body.childNodes[0].tagName == "PRE" || document.body.children.length == 0)) {
	const child = document.body.children.length ? document.body.childNodes[0] : document.body;
	const data = extractData(child.innerText);
	if (data) {
		chrome.runtime.sendMessage({ init: true }, options => processData(data, options));
	}
}

function extractData(rawText) {
	const text = rawText.trim();
	let tokens;

	function test(text) {
		return ((text.charAt(0) == "[" && text.charAt(text.length - 1) == "]") || (text.charAt(0) == "{" && text.charAt(text.length - 1) == "}"));
	}

	if (test(text))
		return {
			text: rawText,
			offset: 0
		};
	tokens = text.match(/^([^\s(]*)\s*\(([\s\S]*)\)\s*;?$/);
	if (tokens && tokens[1] && tokens[2]) {
		if (test(tokens[2].trim()))
			return {
				fnName: tokens[1],
				text: tokens[2],
				offset: rawText.indexOf(tokens[2])
			};
	}
}

function processData(data, options) {
	let jsonText;

	function formatToHTML(fnName, offset) {
		if (!jsonText)
			return;
		chrome.runtime.sendMessage({
			jsonToHTML: true,
			json: jsonText,
			fnName: fnName,
			offset: offset
		}, result => {
			if (result.html) {
				displayUI(result.theme, result.html);
			}
			if (result.error) {
				displayError(result.error, result.loc, result.offset);
			}
		});
		try {
			jsonObject = JSON.parse(jsonText);
		} catch (e) {
			// ignored
		}
	}

	if ((window == top || options.injectInFrame) && data) {
		jsonText = data.text;
		formatToHTML(data.fnName, data.offset);
	}
}

function displayError(error, loc, offset) {
	const link = document.createElement("link");
	const pre = document.body.firstChild.firstChild;
	const text = pre.textContent.substring(offset);
	const range = document.createRange();
	const imgError = document.createElement("img");
	const content = document.createElement("div");
	const errorPosition = document.createElement("span");
	const container = document.createElement("div");
	const closeButton = document.createElement("div");
	const ranges = [];
	let startRange = 0, indexRange = 0, endRange;
	link.rel = "stylesheet";
	link.type = "text/css";
	link.href = chrome.runtime.getURL("css/content-error.css");
	document.head.appendChild(link);
	while (indexRange != -1) {
		indexRange = text.indexOf("\n", startRange);
		ranges.push(startRange);
		startRange = indexRange + 1;
	}
	startRange = ranges[loc.first_line - 1] + loc.first_column + offset;
	endRange = ranges[loc.last_line - 1] + loc.last_column + offset;
	range.setStart(pre, startRange);
	if (startRange == endRange - 1)
		range.setEnd(pre, startRange);
	else
		range.setEnd(pre, endRange);
	errorPosition.className = "error-position";
	errorPosition.id = "error-position";
	range.surroundContents(errorPosition);
	imgError.src = chrome.runtime.getURL("resources/error-icon.gif");
	errorPosition.insertBefore(imgError, errorPosition.firstChild);
	content.className = "content";
	closeButton.className = "close-error";
	closeButton.onclick = () => content.parentElement.removeChild(content);
	content.textContent = error;
	content.appendChild(closeButton);
	container.className = "container";
	container.appendChild(content);
	errorPosition.parentNode.insertBefore(container, errorPosition.nextSibling);
	location.hash = "error-position";
	history.replaceState({}, "", "#");
}

function displayUI(theme, html) {
	const baseStyleElement = document.createElement("link");
	baseStyleElement.rel = "stylesheet";
	baseStyleElement.type = "text/css";
	baseStyleElement.href = chrome.runtime.getURL("css/jsonvue-core.css");
	document.head.appendChild(baseStyleElement);
	const userStyleElement = document.createElement("style");
	userStyleElement.appendChild(document.createTextNode(theme));
	document.head.appendChild(userStyleElement);
	document.body.innerHTML = html;
	collapsers = document.querySelectorAll("#json .collapsible .collapsible");
	const statusElement = document.createElement("div");
	statusElement.className = "status";
	const copyPathElement = document.createElement("div");
	copyPathElement.className = "copy-path";
	statusElement.appendChild(copyPathElement);
	document.body.appendChild(statusElement);
	const toolboxElement = document.createElement("div");
	toolboxElement.className = "toolbox";
	const expandElement = document.createElement("span");
	expandElement.title = "expand all";
	expandElement.innerText = "+";
	const reduceElement = document.createElement("span");
	reduceElement.title = "reduce all";
	reduceElement.innerText = "-";
	toolboxElement.appendChild(expandElement);
	toolboxElement.appendChild(reduceElement);
	document.body.appendChild(toolboxElement);
	document.body.addEventListener("click", ontoggle, false);
	document.body.addEventListener("mouseover", onmouseMove, false);
	document.body.addEventListener("click", onmouseClick, false);
	document.body.addEventListener("contextmenu", onContextMenu, false);
	expandElement.addEventListener("click", onexpand, false);
	reduceElement.addEventListener("click", onreduce, false);
	copyPathElement.addEventListener("click", event => {
		if (event.isTrusted === false)
			return;
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: statusElement.innerText
		});
	}, false);
}

function ontoggle(event) {
	const target = event.target;
	let collapsed;
	if (event.target.className == "collapser") {
		collapsed = target.parentNode.getElementsByClassName("collapsible")[0];
		if (collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.remove("collapsed");
		else
			collapsed.parentNode.classList.add("collapsed");
	}
}

function onexpand() {
	collapsers.forEach(collapsed => {
		if (collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.remove("collapsed");
	});
}

function onreduce() {
	collapsers.forEach(collapsed => {
		if (!collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.add("collapsed");
	});
}

function getParentLI(element) {
	if (element.tagName != "LI")
		while (element && element.tagName != "LI")
			element = element.parentNode;
	if (element && element.tagName == "LI")
		return element;
}

const onmouseMove = (() => {
	let hoveredLI;

	function onmouseOut() {
		const statusElement = document.querySelector(".status");
		if (hoveredLI) {
			hoveredLI.firstChild.classList.remove("hovered");
			hoveredLI = null;
			statusElement.innerText = "";
			jsonSelector = [];
		}
	}

	return event => {
		if (event.isTrusted === false)
			return;
		const statusElement = document.querySelector(".status");
		let str = "";
		let element = getParentLI(event.target);
		if (element) {
			jsonSelector = [];
			if (hoveredLI)
				hoveredLI.firstChild.classList.remove("hovered");
			hoveredLI = element;
			element.firstChild.classList.add("hovered");
			do {
				if (element.parentNode.classList.contains("array")) {
					const index = [].indexOf.call(element.parentNode.children, element);
					str = "[" + index + "]" + str;
					jsonSelector.unshift(index);
				}
				if (element.parentNode.classList.contains("obj")) {
					const key = element.firstChild.firstChild.innerText;
					str = "." + key + str;
					jsonSelector.unshift(key);
				}
				element = element.parentNode.parentNode.parentNode;
			} while (element.tagName == "LI");
			if (str.charAt(0) == ".")
				str = str.substring(1);
			statusElement.innerText = str;
			return;
		}
		onmouseOut();
	};
})();

function onmouseClick(event) {
	if (selectedLI)
		selectedLI.firstChild.classList.remove("selected");
	selectedLI = getParentLI(event.target);
	if (selectedLI) {
		selectedLI.firstChild.classList.add("selected");
	}
}

function onContextMenu(event) {
	if (event.isTrusted === false)
		return;
	const currentLI = getParentLI(event.target);
	const statusElement = document.querySelector(".status");
	if (currentLI) {
		let value = jsonObject;
		jsonSelector.forEach(propertyName => value = value[propertyName]);
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: statusElement.innerText,
			value: typeof value == "object" ? JSON.stringify(value) : value
		});
	} else {
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: "",
			value: jsonObject
		});
	}
}

function copy(value) {
	return navigator.clipboard.writeText(value);
}<commit_msg>fix value<commit_after>/* global navigator, window, document, chrome, location, history, top */

let collapsers, jsonObject, jsonSelector, selectedLI;
chrome.runtime.onMessage.addListener(message => {
	if (message.copy) {
		copy(message.value);
	}
});
if (document.body && (document.body.childNodes[0] && document.body.childNodes[0].tagName == "PRE" || document.body.children.length == 0)) {
	const child = document.body.children.length ? document.body.childNodes[0] : document.body;
	const data = extractData(child.innerText);
	if (data) {
		chrome.runtime.sendMessage({ init: true }, options => processData(data, options));
	}
}

function extractData(rawText) {
	const text = rawText.trim();
	let tokens;

	function test(text) {
		return ((text.charAt(0) == "[" && text.charAt(text.length - 1) == "]") || (text.charAt(0) == "{" && text.charAt(text.length - 1) == "}"));
	}

	if (test(text))
		return {
			text: rawText,
			offset: 0
		};
	tokens = text.match(/^([^\s(]*)\s*\(([\s\S]*)\)\s*;?$/);
	if (tokens && tokens[1] && tokens[2]) {
		if (test(tokens[2].trim()))
			return {
				fnName: tokens[1],
				text: tokens[2],
				offset: rawText.indexOf(tokens[2])
			};
	}
}

function processData(data, options) {
	let jsonText;

	function formatToHTML(fnName, offset) {
		if (!jsonText)
			return;
		chrome.runtime.sendMessage({
			jsonToHTML: true,
			json: jsonText,
			fnName: fnName,
			offset: offset
		}, result => {
			if (result.html) {
				displayUI(result.theme, result.html);
			}
			if (result.error) {
				displayError(result.error, result.loc, result.offset);
			}
		});
		try {
			jsonObject = JSON.parse(jsonText);
		} catch (e) {
			// ignored
		}
	}

	if ((window == top || options.injectInFrame) && data) {
		jsonText = data.text;
		formatToHTML(data.fnName, data.offset);
	}
}

function displayError(error, loc, offset) {
	const link = document.createElement("link");
	const pre = document.body.firstChild.firstChild;
	const text = pre.textContent.substring(offset);
	const range = document.createRange();
	const imgError = document.createElement("img");
	const content = document.createElement("div");
	const errorPosition = document.createElement("span");
	const container = document.createElement("div");
	const closeButton = document.createElement("div");
	const ranges = [];
	let startRange = 0, indexRange = 0, endRange;
	link.rel = "stylesheet";
	link.type = "text/css";
	link.href = chrome.runtime.getURL("css/content-error.css");
	document.head.appendChild(link);
	while (indexRange != -1) {
		indexRange = text.indexOf("\n", startRange);
		ranges.push(startRange);
		startRange = indexRange + 1;
	}
	startRange = ranges[loc.first_line - 1] + loc.first_column + offset;
	endRange = ranges[loc.last_line - 1] + loc.last_column + offset;
	range.setStart(pre, startRange);
	if (startRange == endRange - 1)
		range.setEnd(pre, startRange);
	else
		range.setEnd(pre, endRange);
	errorPosition.className = "error-position";
	errorPosition.id = "error-position";
	range.surroundContents(errorPosition);
	imgError.src = chrome.runtime.getURL("resources/error-icon.gif");
	errorPosition.insertBefore(imgError, errorPosition.firstChild);
	content.className = "content";
	closeButton.className = "close-error";
	closeButton.onclick = () => content.parentElement.removeChild(content);
	content.textContent = error;
	content.appendChild(closeButton);
	container.className = "container";
	container.appendChild(content);
	errorPosition.parentNode.insertBefore(container, errorPosition.nextSibling);
	location.hash = "error-position";
	history.replaceState({}, "", "#");
}

function displayUI(theme, html) {
	const baseStyleElement = document.createElement("link");
	baseStyleElement.rel = "stylesheet";
	baseStyleElement.type = "text/css";
	baseStyleElement.href = chrome.runtime.getURL("css/jsonvue-core.css");
	document.head.appendChild(baseStyleElement);
	const userStyleElement = document.createElement("style");
	userStyleElement.appendChild(document.createTextNode(theme));
	document.head.appendChild(userStyleElement);
	document.body.innerHTML = html;
	collapsers = document.querySelectorAll("#json .collapsible .collapsible");
	const statusElement = document.createElement("div");
	statusElement.className = "status";
	const copyPathElement = document.createElement("div");
	copyPathElement.className = "copy-path";
	statusElement.appendChild(copyPathElement);
	document.body.appendChild(statusElement);
	const toolboxElement = document.createElement("div");
	toolboxElement.className = "toolbox";
	const expandElement = document.createElement("span");
	expandElement.title = "expand all";
	expandElement.innerText = "+";
	const reduceElement = document.createElement("span");
	reduceElement.title = "reduce all";
	reduceElement.innerText = "-";
	toolboxElement.appendChild(expandElement);
	toolboxElement.appendChild(reduceElement);
	document.body.appendChild(toolboxElement);
	document.body.addEventListener("click", ontoggle, false);
	document.body.addEventListener("mouseover", onmouseMove, false);
	document.body.addEventListener("click", onmouseClick, false);
	document.body.addEventListener("contextmenu", onContextMenu, false);
	expandElement.addEventListener("click", onexpand, false);
	reduceElement.addEventListener("click", onreduce, false);
	copyPathElement.addEventListener("click", event => {
		if (event.isTrusted === false)
			return;
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: statusElement.innerText
		});
	}, false);
}

function ontoggle(event) {
	const target = event.target;
	let collapsed;
	if (event.target.className == "collapser") {
		collapsed = target.parentNode.getElementsByClassName("collapsible")[0];
		if (collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.remove("collapsed");
		else
			collapsed.parentNode.classList.add("collapsed");
	}
}

function onexpand() {
	collapsers.forEach(collapsed => {
		if (collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.remove("collapsed");
	});
}

function onreduce() {
	collapsers.forEach(collapsed => {
		if (!collapsed.parentNode.classList.contains("collapsed"))
			collapsed.parentNode.classList.add("collapsed");
	});
}

function getParentLI(element) {
	if (element.tagName != "LI")
		while (element && element.tagName != "LI")
			element = element.parentNode;
	if (element && element.tagName == "LI")
		return element;
}

const onmouseMove = (() => {
	let hoveredLI;

	function onmouseOut() {
		const statusElement = document.querySelector(".status");
		if (hoveredLI) {
			hoveredLI.firstChild.classList.remove("hovered");
			hoveredLI = null;
			statusElement.innerText = "";
			jsonSelector = [];
		}
	}

	return event => {
		if (event.isTrusted === false)
			return;
		const statusElement = document.querySelector(".status");
		let str = "";
		let element = getParentLI(event.target);
		if (element) {
			jsonSelector = [];
			if (hoveredLI)
				hoveredLI.firstChild.classList.remove("hovered");
			hoveredLI = element;
			element.firstChild.classList.add("hovered");
			do {
				if (element.parentNode.classList.contains("array")) {
					const index = [].indexOf.call(element.parentNode.children, element);
					str = "[" + index + "]" + str;
					jsonSelector.unshift(index);
				}
				if (element.parentNode.classList.contains("obj")) {
					const key = element.firstChild.firstChild.innerText;
					str = "." + key + str;
					jsonSelector.unshift(key);
				}
				element = element.parentNode.parentNode.parentNode;
			} while (element.tagName == "LI");
			if (str.charAt(0) == ".")
				str = str.substring(1);
			statusElement.innerText = str;
			return;
		}
		onmouseOut();
	};
})();

function onmouseClick(event) {
	if (selectedLI)
		selectedLI.firstChild.classList.remove("selected");
	selectedLI = getParentLI(event.target);
	if (selectedLI) {
		selectedLI.firstChild.classList.add("selected");
	}
}

function onContextMenu(event) {
	if (event.isTrusted === false)
		return;
	const currentLI = getParentLI(event.target);
	const statusElement = document.querySelector(".status");
	if (currentLI) {
		let value = jsonObject;
		jsonSelector.forEach(propertyName => value = value[propertyName]);
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: statusElement.innerText,
			value: typeof value == "object" ? JSON.stringify(value) : value
		});
	} else {
		chrome.runtime.sendMessage({
			copyPropertyPath: true,
			path: "",
			value: JSON.stringify(jsonObject)
		});
	}
}

function copy(value) {
	return navigator.clipboard.writeText(value);
}<|endoftext|>


<commit_before>/*
  Copyright 2015 Leafbird
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

(function() {

'use strict';

leafbird.element = new Element();

/**
 * Element provides a set of functions to get, filter and find elements
 * in json structure. Use this class methods to manipulate form object
 * before it is rendered.
 *
 * @class
 */
function Element() {

  var element = this;

  element.find = find;
  element.getElements = getElements;

  var configs;

  /**
   * @todo Write JSDoc here
   * { function_description }
   *
   * @param   {string}  property  Name of key in json object.
   * @param   {string}  _value    Value expected to key.
   *
   * @return  {array}   List of items that match with json object.
   */
  function find(property, _value) {
    return findElement(property, _value);
  }

  /**
   * @todo Write JSDoc here
   * { function_description }
   *
   * @param   {string}  _attr Attribute to get specific element(s) from json object.
   *
   * @return  {array}   List of items that match with json object.
   */
  function getElements(_attr) {

    configs = leafbird.configure();

    if (!configs || !configs.json)
      throw new Error('JSON is not valid.');

    var reducedJson = [];
    var index = (_attr && _attr.indexOf('*') === 0) ? 1 : 0;

    if (_attr === undefined)
      reducedJson.push(configs.json);
    else if (_attr.indexOf('#') == index)
      reducedJson = findElement('id', _attr.substring(index + 1), index);
    else if (_attr.indexOf('.') == index)
      reducedJson = findElement('class', _attr.substring(index + 1), index);
    else if (_attr.indexOf(':') == index)
      reducedJson = findElement('name', _attr.substring(index + 1), index);
    else
      throw new SyntaxError('JSONAttribute ' + _attr + ' is not valid.');

    return reducedJson;
  }

  /**
   * @todo Write JSDoc here
   * { function_description }
   *
   * @param   {string}  property    Name of key in json object.
   * @param   {string}  _value      Value expected to key.
   * @param   {boolean} _contains   When true verify if only root of value is matching.
   * @param   {object}  _json       New context of json object in recursive calls.
   *
   * @return  {array}   List of items that match with json object.
   */
  function findElement(property, _value, _contains, _json) {

    configs = leafbird.configure();
    var arrFound = [];
    var obj = (_json === undefined) ? configs.json : _json;

    for (var key in obj) {
      if (key == property && (_value === undefined ||
          (_contains && obj[property].indexOf(_value) > -1) ||
          (!_contains && obj[property] == _value))) {
        arrFound.push(obj);
      }

      if (obj[key] instanceof Object) {
        var found = findElement(property, _value, _contains, obj[key]);
        if (found.length > 0)
          arrFound = arrFound.concat(found);
      }
    }

    return arrFound;
  }
}

})();
<commit_msg>Jsdoc to element file.<commit_after>/*
  Copyright 2015 Leafbird
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

(function() {

'use strict';

leafbird.element = new Element();

/**
 * Element provides a set of functions to get, filter and find elements
 * in json structure. Use this class methods to manipulate form object
 * before it is rendered.
 *
 * @class
 */
function Element() {

  var element = this;

  element.find = find;
  element.getElements = getElements;

  var configs;

  /**
   * Funtion to find a element in json (group or field), it match a property(key)
   * and value then return a array with objects and its siblings.
   *
   * @param   {string}  property  Name of key in json object.
   * @param   {string}  _value    Value expected to key.
   *
   * @return  {array}   List of items that match with json object.
   */
  function find(property, _value) {
    return findElement(property, _value);
  }

  /**
   * Returns elements found by attribute, when _attr is undefined returns whole
   * json. It is a helper to build finds using this order: contains, property and
   * value. When start with contains(*) it find values that contains string value.
   *  -> # = id; #value;
   *  -> . = class; .value;
   *  -> : = name; :name;
   *  -> * = contains; *.partValue;
   *
   * @param   {string}  _attr Attribute to get specific element(s) from json object.
   *
   * @return  {array}   List of items that match with json object.
   */
  function getElements(_attr) {

    configs = leafbird.configure();

    if (!configs || !configs.json)
      throw new Error('JSON is not valid.');

    var reducedJson = [];
    var index = (_attr && _attr.indexOf('*') === 0) ? 1 : 0;

    if (_attr === undefined)
      reducedJson.push(configs.json);
    else if (_attr.indexOf('#') == index)
      reducedJson = findElement('id', _attr.substring(index + 1), index);
    else if (_attr.indexOf('.') == index)
      reducedJson = findElement('class', _attr.substring(index + 1), index);
    else if (_attr.indexOf(':') == index)
      reducedJson = findElement('name', _attr.substring(index + 1), index);
    else
      throw new SyntaxError('JSONAttribute ' + _attr + ' is not valid.');

    return reducedJson;
  }

  /**
   * Funtion recursive to find a element in json (group or field), it match a
   * property(key) and value then return a array with objects and its siblings.
   *
   * @param   {string}  property    Name of key in json object.
   * @param   {string}  _value      Value expected to key.
   * @param   {boolean} _contains   When true verify if only root of value is matching.
   * @param   {object}  _json       New context of json object in recursive calls.
   *
   * @return  {array}   List of items that match with json object.
   */
  function findElement(property, _value, _contains, _json) {

    configs = leafbird.configure();
    var arrFound = [];
    var obj = (_json === undefined) ? configs.json : _json;

    for (var key in obj) {
      if (key == property && (_value === undefined ||
          (_contains && obj[property].indexOf(_value) > -1) ||
          (!_contains && obj[property] == _value))) {
        arrFound.push(obj);
      }

      if (obj[key] instanceof Object) {
        var found = findElement(property, _value, _contains, obj[key]);
        if (found.length > 0)
          arrFound = arrFound.concat(found);
      }
    }

    return arrFound;
  }
}

})();
<|endoftext|>


<commit_before>var MapBuilder = function(args){

  this.init = function(constructorParams) {

    //Add the loader div & its styles next to our root element while hiding the root
    //HTML
    const root = document.getElementById('root');
    if (root) {
      const loaderDiv = document.createElement('div');
      loaderDiv.classList.add('landing-loader__active');
      loaderDiv.classList.add('hidden');
      root.parentNode.insertBefore(loaderDiv, root.nextSibling);

      const loaderSpinner = document.createElement('div');
      loaderSpinner.classList.add('landing-loader__spinner');
      loaderDiv.appendChild(loaderSpinner);

      const loaderSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      loaderSvg.setAttribute('width', '50');
      loaderSvg.setAttribute('height', '50');
      loaderSpinner.appendChild(loaderSvg);

      const loaderG = document.createElementNS('http://www.w3.org/2000/svg', 'g');
      loaderG.setAttribute('transform', 'translate(25,25) rotate(-90)');
      loaderSvg.appendChild(loaderG);

      const loaderPathOne = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      loaderPathOne.setAttribute('d', 'M0,25A25,25 0 1,1 0,-25A25,25 0 1,1 0,25M0,20A20,20 0 1,0 0,-20A20,20 0 1,0 0,20Z');
      loaderPathOne.setAttribute('style', 'fill: rgb(255, 255, 255); stroke: rgb(204, 204, 204)');
      loaderG.appendChild(loaderPathOne);

      const loaderPathTwo = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      loaderPathTwo.classList.add('foreground');
      loaderPathTwo.setAttribute('d', 'M1.5308084989341915e-15,-25A25,25 0 0,1 25,0L20,0A20,20 0 0,0 1.2246467991473533e-15,-20Z');
      loaderPathTwo.setAttribute('style', 'fill: rgb(85, 85, 85)');
      loaderPathTwo.setAttribute('transform', 'rotate(709.287459262793)');
      loaderG.appendChild(loaderPathTwo);

      // Associated CSS
      const styles = `
      #root {
        display: none;
      }
      #share-modal {
        display: none;
      }
      @keyframes hold-loader {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(360deg);
        }
      }

      .landing-loader__active {
        display: block;
        background: rgba(220, 220, 220, 0.75);
        position: absolute;
        height: 100%;
        width: 100%;
        z-index: 5;
        left: 0;
        top: 0;
      }
      .landing-loader__active .foreground {
        animation: hold-loader 0.95s cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite;
      }
      .landing-loader__spinner {
        transform: translate(-50%, -50%);
        position: absolute;
        height: 50px;
        width: 50px;
        left: 50%;
        top: 50%;
      }
      `;

      const styleSheet = document.createElement('style');
      styleSheet.type = 'text/css';
      styleSheet.innerText = styles;
      document.head.appendChild(styleSheet);
    }

    // Dynamically add meta tags if they don't already exist
    const currentMetaTags = document.getElementsByTagName('meta');
    let currentCharsetTag, currentMobileTag;

    for (var i = 0; i < currentMetaTags.length; i++) {
      const content = currentMetaTags[i].getAttribute('content');
      if (content === 'text/html; charset=utf-8') {
        currentCharsetTag = true;
      } else if (content === 'width=device-width, initial-scale=1.0') {
        currentMobileTag = true;
      }
    }
    if (!currentCharsetTag && document.getElementsByTagName('body')[0]) {
      const metaCharset = document.createElement('meta');
      metaCharset.httpEquiv = 'Content-Type';
      metaCharset.content = 'text/html; charset=utf-8';
      document.getElementsByTagName('body')[0].appendChild(metaCharset);
    }

    if (!currentMobileTag && document.getElementsByTagName('body')[0]) {
      const metaMobileDevice = document.createElement('meta');
      metaMobileDevice.name = 'viewport';
      metaMobileDevice.content = 'width=device-width, initial-scale=1.0';
      document.getElementsByTagName('body')[0].appendChild(metaMobileDevice);
    }

    var scripts = document.getElementsByTagName('script');
    var version;
    var newBase;
    for (var j = 0; j < scripts.length; j++) {
      if (scripts[j].id === 'library-load') {
        newBase = scripts[j].src;
        version = scripts[j].getAttribute('version') || constructorParams.version;
      }
    }
    newBase = newBase.split(version)[0] + version;
    window._app = {
      cache: version,
      esri: '#{esriVersion}',
      base: newBase
    };

    function makePath (base, path) {
      var position = base.length - 1;
      return !path ?
        (base.indexOf('/', position) !== position ? base + '/' : base) :
        (base.indexOf('/', position) !== position ?
          base + '/' + path :
          base + path
        );
    }
    constructorParams.cssPath = makePath(newBase, 'css');

    var base = makePath(newBase);

    window.dojoConfig = {
      parseOnLoad: false,
      async: true,
      packages: [
        { name: 'js', location: makePath(base, 'js') }
      ],
      deps: ['dojo/ready'],
      callback: function () {
        require(['js/libraryMain'], function(libraryMain) {
          libraryMain.default.startup();
          libraryMain.default.configureApp(constructorParams);
          libraryMain.default.lazyloadAssets(constructorParams);
          libraryMain.default.initializeApp(constructorParams);
        });
      }
    };

    function loadRequiredCSS() {
      const css = `
        @font-face {
          font-family: 'Fira Sans';
          src: url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.woff2') format('woff2'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.ttf') format('ttf'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.woff') format('woff'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.woff2') format('woff2'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.ttf') format('ttf'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.woff') format('woff');
          font-weight: normal;
          font-style: normal;
        }

        .layer-transparency input[type=range]::-webkit-slider-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .layer-transparency input[type=range]::-moz-range-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .layer-transparency input[type=range]::-ms-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .tree-icon {
          background: url('https://my.gfw-mapbuilder.org/img/tree.png') no-repeat center;
        }

        .forest-icon {
          background: url('https://my.gfw-mapbuilder.org/img/forest.png') no-repeat center;
        }

        .chart-icon {
          background: url('https://my.gfw-mapbuilder.org/img/chart-icon.svg') no-repeat center;
        }

        .print-icon {
          background: url('https://my.gfw-mapbuilder.org/img/print-icon.svg') no-repeat center;
        }

        .subscribe-icon {
          background: url('https://my.gfw-mapbuilder.org/img/subscribe-icon.svg') no-repeat center;
        }
      `;

      const styleTag = document.createElement('style');
      styleTag.type = 'text/css';
      styleTag.appendChild(document.createTextNode(css));
      document.getElementsByTagName('head')[0].appendChild(styleTag);
    }

    function loadjsfile(filename, options) {
      const script = document.createElement('script');
      script.src = filename;
      if (options) {
        Object.entries(options).forEach((item) => {
          const [ attribute, attributeValue ] = item;
          script[attribute] = attributeValue;
        });
      }
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    loadjsfile('https://my.gfw-mapbuilder.org/js/arcgis-api-mapbuilder-1.2/dojo/dojo.js');
    loadjsfile('https://cdnjs.cloudflare.com/ajax/libs/vega/4.2.0/vega.min.js', { charset: 'UTF-8' });
    loadRequiredCSS();

    /*eslint-disable */
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    /*eslint-enable */
  };

  window.customApp = args;

  this.constructorArgs = args;
  this.init(args);
};

window.MapBuilder = MapBuilder;
<commit_msg>Only adding a loader if the #root element exists to append it to<commit_after>var MapBuilder = function(args){

  this.init = function(constructorParams) {

    //Add the loader div & its styles next to our root element while hiding the root
    //HTML
    // const root = document.getElementById('root');
    // if (root) {
    //   const loaderDiv = document.createElement('div');
    //   loaderDiv.classList.add('landing-loader__active');
    //   loaderDiv.classList.add('hidden');
    //   root.parentNode.insertBefore(loaderDiv, root.nextSibling);
    //
    //   const loaderSpinner = document.createElement('div');
    //   loaderSpinner.classList.add('landing-loader__spinner');
    //   loaderDiv.appendChild(loaderSpinner);
    //
    //   const loaderSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    //   loaderSvg.setAttribute('width', '50');
    //   loaderSvg.setAttribute('height', '50');
    //   loaderSpinner.appendChild(loaderSvg);
    //
    //   const loaderG = document.createElementNS('http://www.w3.org/2000/svg', 'g');
    //   loaderG.setAttribute('transform', 'translate(25,25) rotate(-90)');
    //   loaderSvg.appendChild(loaderG);
    //
    //   const loaderPathOne = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    //   loaderPathOne.setAttribute('d', 'M0,25A25,25 0 1,1 0,-25A25,25 0 1,1 0,25M0,20A20,20 0 1,0 0,-20A20,20 0 1,0 0,20Z');
    //   loaderPathOne.setAttribute('style', 'fill: rgb(255, 255, 255); stroke: rgb(204, 204, 204)');
    //   loaderG.appendChild(loaderPathOne);
    //
    //   const loaderPathTwo = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    //   loaderPathTwo.classList.add('foreground');
    //   loaderPathTwo.setAttribute('d', 'M1.5308084989341915e-15,-25A25,25 0 0,1 25,0L20,0A20,20 0 0,0 1.2246467991473533e-15,-20Z');
    //   loaderPathTwo.setAttribute('style', 'fill: rgb(85, 85, 85)');
    //   loaderPathTwo.setAttribute('transform', 'rotate(709.287459262793)');
    //   loaderG.appendChild(loaderPathTwo);
    //
    //   // Associated CSS
    //   const styles = `
    //   #root {
    //     display: none;
    //   }
    //   #share-modal {
    //     display: none;
    //   }
    //   @keyframes hold-loader {
    //     from {
    //       transform: rotate(0deg);
    //     }
    //     to {
    //       transform: rotate(360deg);
    //     }
    //   }
    //
    //   .landing-loader__active {
    //     display: block;
    //     background: rgba(220, 220, 220, 0.75);
    //     position: absolute;
    //     height: 100%;
    //     width: 100%;
    //     z-index: 5;
    //     left: 0;
    //     top: 0;
    //   }
    //   .landing-loader__active .foreground {
    //     animation: hold-loader 0.95s cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite;
    //   }
    //   .landing-loader__spinner {
    //     transform: translate(-50%, -50%);
    //     position: absolute;
    //     height: 50px;
    //     width: 50px;
    //     left: 50%;
    //     top: 50%;
    //   }
    //   `;
    //
    //   const styleSheet = document.createElement('style');
    //   styleSheet.type = 'text/css';
    //   styleSheet.innerText = styles;
    //   document.head.appendChild(styleSheet);
    // }

    // Dynamically add meta tags if they don't already exist
    const currentMetaTags = document.getElementsByTagName('meta');
    let currentCharsetTag, currentMobileTag;

    for (var i = 0; i < currentMetaTags.length; i++) {
      const content = currentMetaTags[i].getAttribute('content');
      if (content === 'text/html; charset=utf-8') {
        currentCharsetTag = true;
      } else if (content === 'width=device-width, initial-scale=1.0') {
        currentMobileTag = true;
      }
    }
    if (!currentCharsetTag && document.getElementsByTagName('body')[0]) {
      const metaCharset = document.createElement('meta');
      metaCharset.httpEquiv = 'Content-Type';
      metaCharset.content = 'text/html; charset=utf-8';
      document.getElementsByTagName('body')[0].appendChild(metaCharset);
    }

    if (!currentMobileTag && document.getElementsByTagName('body')[0]) {
      const metaMobileDevice = document.createElement('meta');
      metaMobileDevice.name = 'viewport';
      metaMobileDevice.content = 'width=device-width, initial-scale=1.0';
      document.getElementsByTagName('body')[0].appendChild(metaMobileDevice);
    }

    var scripts = document.getElementsByTagName('script');
    var version;
    var newBase;
    for (var j = 0; j < scripts.length; j++) {
      if (scripts[j].id === 'library-load') {
        newBase = scripts[j].src;
        version = scripts[j].getAttribute('version') || constructorParams.version;
      }
    }
    newBase = newBase.split(version)[0] + version;
    window._app = {
      cache: version,
      esri: '#{esriVersion}',
      base: newBase
    };

    function makePath (base, path) {
      var position = base.length - 1;
      return !path ?
        (base.indexOf('/', position) !== position ? base + '/' : base) :
        (base.indexOf('/', position) !== position ?
          base + '/' + path :
          base + path
        );
    }
    constructorParams.cssPath = makePath(newBase, 'css');

    var base = makePath(newBase);

    window.dojoConfig = {
      parseOnLoad: false,
      async: true,
      packages: [
        { name: 'js', location: makePath(base, 'js') }
      ],
      deps: ['dojo/ready'],
      callback: function () {
        require(['js/libraryMain'], function(libraryMain) {
          libraryMain.default.startup();
          libraryMain.default.configureApp(constructorParams);
          libraryMain.default.lazyloadAssets(constructorParams);
          libraryMain.default.initializeApp(constructorParams);
        });
      }
    };

    function loadRequiredCSS() {
      const css = `
        @font-face {
          font-family: 'Fira Sans';
          src: url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.woff2') format('woff2'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.ttf') format('ttf'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-regular-webfont.woff') format('woff'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.woff2') format('woff2'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.ttf') format('ttf'),
              url('https://my.gfw-mapbuilder.org/fonts/firasans-bold-webfont.woff') format('woff');
          font-weight: normal;
          font-style: normal;
        }

        .layer-transparency input[type=range]::-webkit-slider-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .layer-transparency input[type=range]::-moz-range-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .layer-transparency input[type=range]::-ms-thumb {
          background: #fff url('https://my.gfw-mapbuilder.org/img/dot.svg') no-repeat 50% 50%;
        }

        .tree-icon {
          background: url('https://my.gfw-mapbuilder.org/img/tree.png') no-repeat center;
        }

        .forest-icon {
          background: url('https://my.gfw-mapbuilder.org/img/forest.png') no-repeat center;
        }

        .chart-icon {
          background: url('https://my.gfw-mapbuilder.org/img/chart-icon.svg') no-repeat center;
        }

        .print-icon {
          background: url('https://my.gfw-mapbuilder.org/img/print-icon.svg') no-repeat center;
        }

        .subscribe-icon {
          background: url('https://my.gfw-mapbuilder.org/img/subscribe-icon.svg') no-repeat center;
        }
      `;

      const styleTag = document.createElement('style');
      styleTag.type = 'text/css';
      styleTag.appendChild(document.createTextNode(css));
      document.getElementsByTagName('head')[0].appendChild(styleTag);
    }

    function loadjsfile(filename, options) {
      const script = document.createElement('script');
      script.src = filename;
      if (options) {
        Object.entries(options).forEach((item) => {
          const [ attribute, attributeValue ] = item;
          script[attribute] = attributeValue;
        });
      }
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    loadjsfile('https://my.gfw-mapbuilder.org/js/arcgis-api-mapbuilder-1.2/dojo/dojo.js');
    loadjsfile('https://cdnjs.cloudflare.com/ajax/libs/vega/4.2.0/vega.min.js', { charset: 'UTF-8' });
    loadRequiredCSS();

    /*eslint-disable */
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    /*eslint-enable */
  };

  window.customApp = args;

  this.constructorArgs = args;
  this.init(args);
};

window.MapBuilder = MapBuilder;
<|endoftext|>