<commit_before>    $.fn.extend({
        // Special type of select question - passes two values - the answer from
        // the select plus an associated date from a separate input
        eventInput: function(settings) {
            $(this).on("click", function() {
                var selectVal = $(this).attr('data-name');
                var selectDate = $(this).attr('data-date');
                // Only post if value and date have been chosen
                if (selectVal !== undefined && selectDate !== undefined) {
                    var procArray = {};
                    var selectFriendly = $("#tnthproc option:selected").text();
                    var procID = [{ "code": selectVal, "display": selectFriendly,
                            system: "http://snomed.info/sct" }];
                    procArray["resourceType"] = "Procedure";
                    procArray["subject"] = {"reference": "Patient/" + subjectId };
                    procArray["code"] = {"coding": procID};
                    procArray["performedDateTime"] = selectDate;
                    tnthAjax.postProc(subjectId,procArray);
                }
                return false;
            });
        },
    }); // $.fn.extend({

    $(document).ready(function() {

        var eventLoading = '

';
        // Options for datepicker - prevent future dates, no default
        $('.event-element input.datep').each(function(){
            $(this).datepicker({
                dateFormat: 'mm/dd/yy',
                changeMonth: true,
                changeYear: true,
                maxDate: "0"
            });
        });

        // Post to server - uses on click for "Add Event" button
        $("button[id^='tnthproc-submit']").eventInput({
            page_id: 489        });

        // Add/remove disabled from submit button
        function checkSubmit(btnId) {
            if ($(btnId).attr("data-name") != "" && $(btnId).attr("data-date-read") != "") {
                $(btnId).removeClass('disabled').removeAttr('disabled').addClass('pulse');
            } else {
                $(btnId).addClass('disabled').attr('disabled',true).removeClass('pulse');
            }
        }

        // Update submit button when select changes
        $("select[id^='tnthproc']").on('change', function() {
            $("button[id^='tnthproc-submit']").attr("data-name", $(this).val());
            checkSubmit("button[id^='tnthproc-submit']");
        });
        // Update submit button when text input changes (single option)
        $("input[id^='tnthproc-value']").on('change', function() {
            $("button[id^='tnthproc-submit']").attr("data-name", $(this).val());
            checkSubmit("button[id^='tnthproc-submit']");
        });
        // When date changes, update submit button w/ both mm/dd/yyyy and yyyy-mm-dd
        $("input[id^='tnthproc-date']").on('change', function( event ) {
            var passedDate = $(this).val();
            $("button[id^='tnthproc-submit']").attr('data-date-read',passedDate);
            var dateFormatted;
            // Change dates to YYYY-MM-DD
            if (passedDate && passedDate != '') {
                dateFormatted = tnthDates.changeFormat(passedDate);
            }
            $("button[id^='tnthproc-submit']").attr('data-date',dateFormatted);
            checkSubmit("button[id^='tnthproc-submit']");
        });

        // Add Event submit button - click posts to server (in cpro.jquery) and here we add
        // it to the list of previous event
        // Note - this and cpro.jquery both look for on click. could combine.
        $("button[id^='tnthproc-submit']").on("click", function(event){
            // First disable button to prevent double-clicks
            $(this).attr('disabled', true);
            var eventName = $(this).attr('data-name');
            var eventDate = $(this).attr('data-date-read');
            if (eventName != "" && eventDate != "") {
                // First fadeOut the #eventList - we animate opacity to retain the
                // width and height so lower content doesn't go up and down
                $("#eventListtnthproc").animate({opacity: 0}, function() {
                    // Hide the #noEvents text (if showing)
                    $("#noEvents").hide();
                    $(this).html(eventLoading).css('opacity',1);
                    // Clear the inputs
                    $("select[id^='tnthproc']").val('');
                    $("input[id^='tnthproc-value']").val('');
                    $("input[id^='tnthproc-date']").val('');
                    // Clear submit button
                    $("button[id^='tnthproc-submit']").addClass('disabled').removeClass('pulse').attr({
                        "data-name": "",                        "data-date": "",
                        "data-date-read": ""
                    });
                    //TODO GET procedures and repopulate list here (mind the latest ID, as this does?)
                    tnthAjax.getProc(subjectId);
                    // Since we need answer ID from server for delete, reload the eventList
                    /**$("#eventListtnthproc").load("489 #eventListtnthproc  > *", function(){
                        // Popover needs to be called again here b/c of element load
                        $("[rel=popover-confirm]").popover({
                            trigger: 'click',
                            placement: 'right',
                            html: true
                        });
                        // Grab most recent event on load to highlight new entries on reload
                        var mostRecentId = 11891;// populate at page load
                        // Add a "new" icon to ones that were created via ajax submit
                        $("#eventListtnthproc li").each(function() {
                            var eventId = $(this).attr('data-id');
                            if (eventId > mostRecentId) {
                                $(this).append("   Added!");
                            }
                        });
                        // Fade in the eventList with opacity
                        $("#eventListtnthproc").animate({opacity: 1});
                    });*/
                });
            }
        });

        /*** Delete functions ***/
            // Main delete function handled in cpro.js - using rel="popover-confirm"
        $('body').on('click', '.cancel-delete', function() {
            $(this).parents("div.popover").prev('a.confirm-delete').trigger('click');
        });
        // Need to attach delete functionality to body b/c section gets reloaded
        $("body").on('click', ".btn-delete", function() {
            // Get ID for this answer
            var answerId = $(this).parents('li').attr('data-id');
            // Remove from list
            $(this).parents('li').fadeOut('slow', function(){
                $(this).remove();
                // If there's no events left, add status msg back in
                if ($('#eventListtnthproc li').length == 0) {
                    $('#eventListtnthproc').prepend("
You haven't added any procedures.
");
                }
            });
            alert('DELETE api call would be next...');
            // Post delete to server
            /**$.post(appRoot + controller + "/deleteAnswer.json", {
                "data[Answer][id]" : answerId,
                "data[AppController][AppController_id]" : acidValue
            }, "json");*/
            return false;
        });

    });
<commit_msg>procedures refresh - disabled cpro spinner, since I think truenth has something already...<commit_after>    $.fn.extend({
        // Special type of select question - passes two values - the answer from
        // the select plus an associated date from a separate input
        eventInput: function(settings) {
            $(this).on("click", function() {
                var selectVal = $(this).attr('data-name');
                var selectDate = $(this).attr('data-date');
                // Only post if value and date have been chosen
                if (selectVal !== undefined && selectDate !== undefined) {
                    var procArray = {};
                    var selectFriendly = $("#tnthproc option:selected").text();
                    var procID = [{ "code": selectVal, "display": selectFriendly,
                            system: "http://snomed.info/sct" }];
                    procArray["resourceType"] = "Procedure";
                    procArray["subject"] = {"reference": "Patient/" + subjectId };
                    procArray["code"] = {"coding": procID};
                    procArray["performedDateTime"] = selectDate;
                    tnthAjax.postProc(subjectId,procArray);
                }
                return false;
            });
        },
    }); // $.fn.extend({

    $(document).ready(function() {

        //var eventLoading = '

';
        // Options for datepicker - prevent future dates, no default
        $('.event-element input.datep').each(function(){
            $(this).datepicker({
                dateFormat: 'mm/dd/yy',
                changeMonth: true,
                changeYear: true,
                maxDate: "0"
            });
        });

        // Post to server - uses on click for "Add Event" button
        $("button[id^='tnthproc-submit']").eventInput({
            page_id: 489        });

        // Add/remove disabled from submit button
        function checkSubmit(btnId) {
            if ($(btnId).attr("data-name") != "" && $(btnId).attr("data-date-read") != "") {
                $(btnId).removeClass('disabled').removeAttr('disabled').addClass('pulse');
            } else {
                $(btnId).addClass('disabled').attr('disabled',true).removeClass('pulse');
            }
        }

        // Update submit button when select changes
        $("select[id^='tnthproc']").on('change', function() {
            $("button[id^='tnthproc-submit']").attr("data-name", $(this).val());
            checkSubmit("button[id^='tnthproc-submit']");
        });
        // Update submit button when text input changes (single option)
        $("input[id^='tnthproc-value']").on('change', function() {
            $("button[id^='tnthproc-submit']").attr("data-name", $(this).val());
            checkSubmit("button[id^='tnthproc-submit']");
        });
        // When date changes, update submit button w/ both mm/dd/yyyy and yyyy-mm-dd
        $("input[id^='tnthproc-date']").on('change', function( event ) {
            var passedDate = $(this).val();
            $("button[id^='tnthproc-submit']").attr('data-date-read',passedDate);
            var dateFormatted;
            // Change dates to YYYY-MM-DD
            if (passedDate && passedDate != '') {
                dateFormatted = tnthDates.changeFormat(passedDate);
            }
            $("button[id^='tnthproc-submit']").attr('data-date',dateFormatted);
            checkSubmit("button[id^='tnthproc-submit']");
        });

        // Add Event submit button - click posts to server (in cpro.jquery) and here we add
        // it to the list of previous event
        // Note - this and cpro.jquery both look for on click. could combine.
        $("button[id^='tnthproc-submit']").on("click", function(event){
            // First disable button to prevent double-clicks
            $(this).attr('disabled', true);
            var eventName = $(this).attr('data-name');
            var eventDate = $(this).attr('data-date-read');
            if (eventName != "" && eventDate != "") {
                // First fadeOut the #eventList - we animate opacity to retain the
                // width and height so lower content doesn't go up and down
                $("#eventListtnthproc").animate({opacity: 0}, function() {
                    // Hide the #noEvents text (if showing)
                    $("#noEvents").hide();
                    //$(this).html(eventLoading).css('opacity',1);
                    // Clear the inputs
                    $("select[id^='tnthproc']").val('');
                    $("input[id^='tnthproc-value']").val('');
                    $("input[id^='tnthproc-date']").val('');
                    // Clear submit button
                    $("button[id^='tnthproc-submit']").addClass('disabled').removeClass('pulse').attr({
                        "data-name": "",                        "data-date": "",
                        "data-date-read": ""
                    });
                    //TODO GET procedures and repopulate list here (mind the latest ID, as this does?)
                    tnthAjax.getProc(subjectId);
                    // Since we need answer ID from server for delete, reload the eventList
                    /**$("#eventListtnthproc").load("489 #eventListtnthproc  > *", function(){
                        // Popover needs to be called again here b/c of element load
                        $("[rel=popover-confirm]").popover({
                            trigger: 'click',
                            placement: 'right',
                            html: true
                        });
                        // Grab most recent event on load to highlight new entries on reload
                        var mostRecentId = 11891;// populate at page load
                        // Add a "new" icon to ones that were created via ajax submit
                        $("#eventListtnthproc li").each(function() {
                            var eventId = $(this).attr('data-id');
                            if (eventId > mostRecentId) {
                                $(this).append("   Added!");
                            }
                        });
                        // Fade in the eventList with opacity
                        $("#eventListtnthproc").animate({opacity: 1});
                    });*/
                });
            }
        });

        /*** Delete functions ***/
            // Main delete function handled in cpro.js - using rel="popover-confirm"
        $('body').on('click', '.cancel-delete', function() {
            $(this).parents("div.popover").prev('a.confirm-delete').trigger('click');
        });
        // Need to attach delete functionality to body b/c section gets reloaded
        $("body").on('click', ".btn-delete", function() {
            // Get ID for this answer
            var answerId = $(this).parents('li').attr('data-id');
            // Remove from list
            $(this).parents('li').fadeOut('slow', function(){
                $(this).remove();
                // If there's no events left, add status msg back in
                if ($('#eventListtnthproc li').length == 0) {
                    $('#eventListtnthproc').prepend("
You haven't added any procedures.
");
                }
            });
            alert('DELETE api call would be next...');
            // Post delete to server
            /**$.post(appRoot + controller + "/deleteAnswer.json", {
                "data[Answer][id]" : answerId,
                "data[AppController][AppController_id]" : acidValue
            }, "json");*/
            return false;
        });

    });
<|endoftext|>


<commit_before>$(document).ready(function() {
  $(".list--episodes, .list--queue").on("click", function(e) {
    var classList = e.target.classList;
    let $target = $(e.target);

    if (classList.contains("episode_button")) {
      var id = e.target.parentElement.parentElement.parentElement.dataset.id;
      var audioElem = document.querySelector(".audios [data-id='" + id + "']");

      if (classList.contains("episode_button--play")) {
        var $episodeElem = $target.closest(".episode");
        var $closestList = $target.closest(".list");
        if ($closestList.hasClass("list--episodes")) { // from stream
          cbus.audio.setElement(audioElem);
          cbus.audio.play();
        } else { // from queue
          cbus.audio.playQueueItem($episodeElem.index());
        }
      } else if (classList.contains("episode_button--enqueue")) {
        cbus.audio.enqueue(audioElem);
      } else if (classList.contains("episode_button--remove-from-queue")) {
        cbus.audio.removeQueueItem($(e.target).closest(".episode").index());
      } else if (classList.contains("episode_button--download")) {
        cbus.data.downloadEpisode(audioElem);
      } else if (classList.contains("episode_button--completed")) {
        cbus.data.toggleCompleted(audioElem.dataset.id);
      }
    } else if (classList.contains("episode_feed-title")) {
      var url = cbus.data.getEpisodeData({ id: $target.closest(".episode").attr("data-id") }).feedURL;
      cbus.broadcast.send("showPodcastDetail", {
        url: url
      });
    } else if (classList.contains("episode_info-button")) {
      var $episodeElem = $target.closest(".episode");
      console.log($episodeElem);
      if ($episodeElem.hasClass("info-open")) {
        console.log("has");
        $episodeElem.removeClass("info-open");
      } else {
        console.log("no has");
        $(".episode").removeClass("info-open");
        $episodeElem.find(".episode_bottom").scrollTop(0);
        $episodeElem.addClass("info-open");
      }
    } else if (e.target.tagName === "A") {
      e.preventDefault();
      remote.shell.openExternal(e.target.href);
    }
  });

  /* search */

  let searchResultsElem = document.getElementsByClassName("explore_feeds--search-results")[0];
  document.querySelector(".explore_search input").addEventListener("keydown", function(e) {
    if (e.key === "Enter") {
      let query = this.value;

      if (query.length > 0) {
        searchResultsElem.innerHTML = "";

        if (cbus.const.youtubeChannelRegexLoose.test(query)) {
          // YT channel in channel/<ID> or user/<username> format
          request.post("https://podsync.net/api/create", {
            json: {
              url: query,
              format: "video",
              quality: "high",
              page_size: 50
            }
          }, (err, res, body) => {
            if (err || res.statusCode < 200 && res.statusCode >= 300) {
              cbus.ui.showSnackbar(i18n.__("snackbar_error-podcast-detail"), "error");
            } else {
              cbus.broadcast.send("showPodcastDetail", {
                url: "https://podsync.net/" + body.id
              });
            }
          });
        } else if (cbus.const.urlRegex.test(query)) {
          // URL
          cbus.broadcast.send("showPodcastDetail", {
            url: query
          });
        } else {
          // search query
          cbus.server.searchPodcasts(query, function(data) {
            if (data) {
              cbus.broadcast.send("got-search-results")
              for (let i = 0, l = data.length; i < l; i++) {
                searchResultsElem.appendChild(cbus.ui.makeFeedElem(data[i], i, true));
                cbus.data.feedsCache.push(data[i]);
              }
            }
          });

          searchResultsElem.classList.add("visible");
        }
      } else {
        searchResultsElem.classList.add("visible");
      }
    }
  });

  /* player controls */

  $(".player").on("click", function(e) {
    var classList = e.target.classList;
    if (classList.contains("player_button")) {
      if (classList.contains("player_button--backward")) {
        cbus.audio.jump(cbus.audio.DEFAULT_JUMP_AMOUNT_BACKWARD);
      } else if (classList.contains("player_button--forward")) {
        cbus.audio.jump(cbus.audio.DEFAULT_JUMP_AMOUNT_FORWARD);
      } else if (classList.contains("player_button--play")) {
        if (!cbus.audio.element) {
          if (cbus.audio.queue.length > 0) {
            cbus.audio.setElement(cbus.audio.queue[0]);
          }
          cbus.audio.play();
        } else if (cbus.audio.element.paused) {
          cbus.audio.play();
        } else {
          cbus.audio.pause();
        }
      } else if (classList.contains("player_button--next")) {
        cbus.audio.playQueueItem(0);
      } else if (classList.contains("player_button--openclose")) {
        document.body.classList.toggle("player-expanded");
      }
    } else if (classList.contains("player_detail_tab")) {
      if (classList.contains("player_detail_tab--description")) {
          cbus.ui.setPlayerTab(0);
      } else if (classList.contains("player_detail_tab--chapters")) {
        cbus.ui.setPlayerTab(1);
      }
    } else if (classList.contains("player_detail_chapter")) {
      let chapters = cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).chapters;
      cbus.audio.element.currentTime = chapters[Number(e.target.dataset.index)].time;
    } else if (classList.contains("player_detail_description_timelink")) {
      cbus.audio.element.currentTime = cbus.data.parseTimeString(e.target.textContent);
    }
  });

  $(".player_slider").on("input change", function() {
    var proportion = this.value / this.max;
    cbus.audio.element.currentTime = cbus.audio.element.duration * proportion;
  });

  cbus.ui.videoCanvasElement.addEventListener("dblclick", (e) => {
    cbus.ui.setFullscreen(!cbus.ui.browserWindow.isFullScreen());
  });

  /* header actions */

  $(".header_actions").on("click", function(e) {
    var classList = e.target.classList;
    if (classList.contains("header_action")) {
      if (classList.contains("header_action--refresh-episodes")) {
        cbus.data.update();
      }
    }
  });

  /* tabs */

  $("header nav a").on("click", function() {
    var targetId = this.dataset.target;
    cbus.ui.tabs.switch({ id: targetId });
  });

  /* update stream or load from cache */

  var storedEpisodes, lastAudioInfo, lastQueueInfos,
      lastAudioURL, lastAudioTime;

  localforageGetMulti([
    "cbus_feeds_qnp", "cbus_cache_episodes", "cbus_episodes_offline",
    "cbus-last-audio-info", "cbus-last-queue-infos", "cbus-last-audio-url",
    "cbus-last-audio-time", "cbus-last-queue-urls", "cbus_episode_progresses",
    "cbus_feeds", "cbus_episode_completed_statuses"
  ], function(r) {
    if (r.hasOwnProperty("cbus_cache_episodes")) {
      storedEpisodes = r["cbus_cache_episodes"];
    }
    if (r.hasOwnProperty("cbus_episodes_offline")) {
      cbus.data.episodesOffline = r["cbus_episodes_offline"] || [];
    }
    if (r.hasOwnProperty("cbus-last-audio-info")) {
      lastAudioInfo = r["cbus-last-audio-info"];
    }
    if (r.hasOwnProperty("cbus-last-queue-infos")) {
      lastQueueInfos = r["cbus-last-queue-infos"];
    }
    if (r.hasOwnProperty("cbus-last-audio-url")) {
      lastAudioURL = r["cbus-last-audio-url"];
    }
    if (r.hasOwnProperty("cbus-last-audio-time")) {
      lastAudioTime = r["cbus-last-audio-time"];
    }
    if (r.hasOwnProperty("cbus-last-queue-urls")) {
      lastQueueURLs = r["cbus-last-queue-urls"];
    }

    cbus.data.episodeProgresses = r["cbus_episode_progresses"] || [];
    cbus.data.episodeCompletedStatuses = r["cbus_episode_completed_statuses"] || [];
    cbus.data.feedsQNP = r["cbus_feeds_qnp"] || [];

    if (r["cbus_feeds"]) {
      cbus.data.feeds = r["cbus_feeds"].sort(cbus.const.podcastSort);
    } else {
      cbus.data.feeds = [];
    }
    for (let i = 0, l = cbus.data.feeds.length; i < l; i++) {
      cbus.data.feedsCache.push(cbus.data.feeds[i]);
    }
    if (cbus.data.feeds.length > 0) { // there are subscribed feeds
      cbus.ui.tabs.switch({ index: 0 }); // Home tab
    } else { // no subscribed feeds
      cbus.ui.tabs.switch({ index: 3 }); // Explore tab
    }
    cbus.ui.display("feeds");

    fs.readdir(path.join(cbus.const.USERDATA_PATH, "offline_episodes"), function(err, files) {
      for (let i = 0, l = cbus.data.episodesOffline.length; i < l; i++) {
        if (files.indexOf(sha1(cbus.data.episodesOffline[i])) === -1) { // both are arrays of strings
          let episodeURL = cbus.data.episodesOffline[i];
          cbus.data.episodesOffline.splice(i, 1)
          cbus.broadcast.send("offline_episodes_changed", {
            episodeURL: episodeURL
          });
        } else {
          console.log(files)
        }
      }
      localforage.setItem("cbus_episodes_offline", cbus.data.episodesOffline)
    })

    cbus.data.episodesUnsubbed = []

    if (storedEpisodes) {
      // store globally
      cbus.data.episodes = storedEpisodes.filter(function(episodeInfo) {
        var feedInfo = cbus.data.getFeedData({ url: episodeInfo.feedURL });
        if (!feedInfo || feedInfo.isUnsubscribed) { return false; }
        return true;
      });
      if (lastAudioInfo) {
        cbus.data.episodesUnsubbed.push(lastAudioInfo)
      }
      if (lastQueueInfos) {
        for (let i = 0, l = lastQueueInfos.length; i < l; i++) {
          cbus.data.episodesUnsubbed.push(lastQueueInfos[i])
        }
      }
      cbus.data.updateMedias(); // make audio elems and add to DOM
      cbus.ui.display("episodes"); // display the episodes we already have

      if (lastAudioURL) {
        let elem = document.querySelector(`.audios [data-id='${lastAudioURL}']`);
        if (elem) {
          // cbus.audio.setElement(elem, true);
          cbus.audio.setElement(elem);
          if (lastAudioTime) {
            cbus.audio.element.currentTime = lastAudioTime;
            cbus.broadcast.send("audioTick", {
              currentTime: lastAudioTime,
              duration: cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).length
            })
          }
        }
      }

      if (lastQueueURLs) {
        for (let i = 0, l = lastQueueURLs.length; i < l; i++) {
          cbus.audio.enqueue(document.querySelector(`.audios audio[data-id="${ lastQueueURLs[i] }"]`), true)
        }
      }
    } else {
      cbus.ui.firstrunContainerElem.classList.add("visible");
    }

    cbus.data.update(); // look for any new episodes (takes care of displaying and updateMedias-ing)
  });

  /* start loading popular podcasts */

  cbus.server.getPopularPodcasts((popularPodcastInfos) => {
    console.log(popularPodcastInfos)
    let popularPodcastsElem = document.getElementsByClassName("explore_feeds--popular")[0];
    for (let i = 0, l = popularPodcastInfos.length; i < l; i++) {
      popularPodcastsElem.appendChild(
        cbus.ui.makeFeedElem(popularPodcastInfos[i], i, true)
      );
      cbus.data.feedsCache.push(popularPodcastInfos[i]);
    }
  })

  cbus.broadcast.listen("toggleSubscribe", function(e) {
    console.log(e);

    var completeData = arrayFindByKey(cbus.data.feedsCache, "url", e.data.url)[0];
    var subscribed = !!arrayFindByKey(cbus.data.feeds, "url", e.data.url)[0]

    var direction;
    if (e.data.direction) {
      direction = e.data.direction;
    } else {
      if (subscribed) { // already subscribed
        direction = -1;
      } else { // not subscribed
        direction = 1;
      }
    }

    if (direction === -1) {
      cbus.data.unsubscribeFeed({ url: e.data.url }, true);
    } else {
      // complete required data
      // required keys: image, title, url

      cbus.server.getPodcastInfo(e.data.url, (podcastInfo) => {
        if (podcastInfo) {
          e.data.image = podcastInfo.image;
          e.data.title = podcastInfo.title;
          cbus.data.subscribeFeed(e.data, true);
        }
      });
    }

    if (cbus.data.state.podcastDetailCurrentData.url === e.data.url) {
      if (direction === -1) {
        $(".podcast-detail_control--toggle-subscribe").removeClass("subscribed");
        console.log("removed subscribed class");
      } else {
        $(".podcast-detail_control--toggle-subscribe").addClass("subscribed");
        console.log("added subscribed class");
      }
    }
  });

  /* listen for audio change */

  cbus.broadcast.listen("audioChange", function(e) {
    var element = $("audio audio[data-id='" + e.data.id + "']");

    cbus.broadcast.send("audioTick", {
      currentTime: 0,
      duration: element.duration
    });

    cbus.ui.display("player", e.data);

    // /* extract accent color of feed image and apply to player */
    //
    // cbus.ui.colorify({
    //   image: e.data.feed.image,
    //   element: $(".player")
    // });
    // $(".player").addClass("light-colors");
  });

  /* update audio time */

  let playerTimeNowElem = document.getElementsByClassName("player_time--now")[0];
  let playerTimeTotalElem = document.getElementsByClassName("player_time--total")[0];
  let playerSliderElem = document.getElementsByClassName("player_slider")[0];

  cbus.broadcast.listen("audioTick", function(e) {
    /* slider */
    playerSliderElem.value = Math.round(1000 * e.data.currentTime / e.data.duration) || 0;

    /* time indicator */
    playerTimeNowElem.innerHTML = colonSeparateDuration(e.data.currentTime);
    playerTimeTotalElem.innerHTML = colonSeparateDuration(e.data.duration);

    /* record in localforage so we can resume next time */
    localforage.setItem("cbus-last-audio-time", e.data.currentTime);
  });

  /* open podcast detail when podcast name clicked in episode data */

  document.getElementsByClassName("player_detail_feed-title")[0].onclick = function() {
    cbus.broadcast.send("showPodcastDetail", {
      url: cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).feedURL
    });
  };
});

/* shortly after startup, remove from episodesUnsubbed and feedsQNP episodes/feeds not in queue or now playing */
// setTimeout(function() {
//   var episodesStillNeededURLs = []
//   if (cbus.audio.element) {
//     episodesStillNeededURLs.push(cbus.data.getEpisodeData({audioElement: cbus.audio.element}).url)
//   }
// }, 10000)
<commit_msg>Fix firstrun message showing when it shouldn't<commit_after>$(document).ready(function() {
  $(".list--episodes, .list--queue").on("click", function(e) {
    var classList = e.target.classList;
    let $target = $(e.target);

    if (classList.contains("episode_button")) {
      var id = e.target.parentElement.parentElement.parentElement.dataset.id;
      var audioElem = document.querySelector(".audios [data-id='" + id + "']");

      if (classList.contains("episode_button--play")) {
        var $episodeElem = $target.closest(".episode");
        var $closestList = $target.closest(".list");
        if ($closestList.hasClass("list--episodes")) { // from stream
          cbus.audio.setElement(audioElem);
          cbus.audio.play();
        } else { // from queue
          cbus.audio.playQueueItem($episodeElem.index());
        }
      } else if (classList.contains("episode_button--enqueue")) {
        cbus.audio.enqueue(audioElem);
      } else if (classList.contains("episode_button--remove-from-queue")) {
        cbus.audio.removeQueueItem($(e.target).closest(".episode").index());
      } else if (classList.contains("episode_button--download")) {
        cbus.data.downloadEpisode(audioElem);
      } else if (classList.contains("episode_button--completed")) {
        cbus.data.toggleCompleted(audioElem.dataset.id);
      }
    } else if (classList.contains("episode_feed-title")) {
      var url = cbus.data.getEpisodeData({ id: $target.closest(".episode").attr("data-id") }).feedURL;
      cbus.broadcast.send("showPodcastDetail", {
        url: url
      });
    } else if (classList.contains("episode_info-button")) {
      var $episodeElem = $target.closest(".episode");
      console.log($episodeElem);
      if ($episodeElem.hasClass("info-open")) {
        console.log("has");
        $episodeElem.removeClass("info-open");
      } else {
        console.log("no has");
        $(".episode").removeClass("info-open");
        $episodeElem.find(".episode_bottom").scrollTop(0);
        $episodeElem.addClass("info-open");
      }
    } else if (e.target.tagName === "A") {
      e.preventDefault();
      remote.shell.openExternal(e.target.href);
    }
  });

  /* search */

  let searchResultsElem = document.getElementsByClassName("explore_feeds--search-results")[0];
  document.querySelector(".explore_search input").addEventListener("keydown", function(e) {
    if (e.key === "Enter") {
      let query = this.value;

      if (query.length > 0) {
        searchResultsElem.innerHTML = "";

        if (cbus.const.youtubeChannelRegexLoose.test(query)) {
          // YT channel in channel/<ID> or user/<username> format
          request.post("https://podsync.net/api/create", {
            json: {
              url: query,
              format: "video",
              quality: "high",
              page_size: 50
            }
          }, (err, res, body) => {
            if (err || res.statusCode < 200 && res.statusCode >= 300) {
              cbus.ui.showSnackbar(i18n.__("snackbar_error-podcast-detail"), "error");
            } else {
              cbus.broadcast.send("showPodcastDetail", {
                url: "https://podsync.net/" + body.id
              });
            }
          });
        } else if (cbus.const.urlRegex.test(query)) {
          // URL
          cbus.broadcast.send("showPodcastDetail", {
            url: query
          });
        } else {
          // search query
          cbus.server.searchPodcasts(query, function(data) {
            if (data) {
              cbus.broadcast.send("got-search-results")
              for (let i = 0, l = data.length; i < l; i++) {
                searchResultsElem.appendChild(cbus.ui.makeFeedElem(data[i], i, true));
                cbus.data.feedsCache.push(data[i]);
              }
            }
          });

          searchResultsElem.classList.add("visible");
        }
      } else {
        searchResultsElem.classList.add("visible");
      }
    }
  });

  /* player controls */

  $(".player").on("click", function(e) {
    var classList = e.target.classList;
    if (classList.contains("player_button")) {
      if (classList.contains("player_button--backward")) {
        cbus.audio.jump(cbus.audio.DEFAULT_JUMP_AMOUNT_BACKWARD);
      } else if (classList.contains("player_button--forward")) {
        cbus.audio.jump(cbus.audio.DEFAULT_JUMP_AMOUNT_FORWARD);
      } else if (classList.contains("player_button--play")) {
        if (!cbus.audio.element) {
          if (cbus.audio.queue.length > 0) {
            cbus.audio.setElement(cbus.audio.queue[0]);
          }
          cbus.audio.play();
        } else if (cbus.audio.element.paused) {
          cbus.audio.play();
        } else {
          cbus.audio.pause();
        }
      } else if (classList.contains("player_button--next")) {
        cbus.audio.playQueueItem(0);
      } else if (classList.contains("player_button--openclose")) {
        document.body.classList.toggle("player-expanded");
      }
    } else if (classList.contains("player_detail_tab")) {
      if (classList.contains("player_detail_tab--description")) {
          cbus.ui.setPlayerTab(0);
      } else if (classList.contains("player_detail_tab--chapters")) {
        cbus.ui.setPlayerTab(1);
      }
    } else if (classList.contains("player_detail_chapter")) {
      let chapters = cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).chapters;
      cbus.audio.element.currentTime = chapters[Number(e.target.dataset.index)].time;
    } else if (classList.contains("player_detail_description_timelink")) {
      cbus.audio.element.currentTime = cbus.data.parseTimeString(e.target.textContent);
    }
  });

  $(".player_slider").on("input change", function() {
    var proportion = this.value / this.max;
    cbus.audio.element.currentTime = cbus.audio.element.duration * proportion;
  });

  cbus.ui.videoCanvasElement.addEventListener("dblclick", (e) => {
    cbus.ui.setFullscreen(!cbus.ui.browserWindow.isFullScreen());
  });

  /* header actions */

  $(".header_actions").on("click", function(e) {
    var classList = e.target.classList;
    if (classList.contains("header_action")) {
      if (classList.contains("header_action--refresh-episodes")) {
        cbus.data.update();
      }
    }
  });

  /* tabs */

  $("header nav a").on("click", function() {
    var targetId = this.dataset.target;
    cbus.ui.tabs.switch({ id: targetId });
  });

  /* update stream or load from cache */

  var storedEpisodes, lastAudioInfo, lastQueueInfos,
      lastAudioURL, lastAudioTime;

  localforageGetMulti([
    "cbus_feeds_qnp", "cbus_cache_episodes", "cbus_episodes_offline",
    "cbus-last-audio-info", "cbus-last-queue-infos", "cbus-last-audio-url",
    "cbus-last-audio-time", "cbus-last-queue-urls", "cbus_episode_progresses",
    "cbus_feeds", "cbus_episode_completed_statuses"
  ], function(r) {
    if (r.hasOwnProperty("cbus_cache_episodes")) {
      storedEpisodes = r["cbus_cache_episodes"];
    }
    if (r.hasOwnProperty("cbus_episodes_offline")) {
      cbus.data.episodesOffline = r["cbus_episodes_offline"] || [];
    }
    if (r.hasOwnProperty("cbus-last-audio-info")) {
      lastAudioInfo = r["cbus-last-audio-info"];
    }
    if (r.hasOwnProperty("cbus-last-queue-infos")) {
      lastQueueInfos = r["cbus-last-queue-infos"];
    }
    if (r.hasOwnProperty("cbus-last-audio-url")) {
      lastAudioURL = r["cbus-last-audio-url"];
    }
    if (r.hasOwnProperty("cbus-last-audio-time")) {
      lastAudioTime = r["cbus-last-audio-time"];
    }
    if (r.hasOwnProperty("cbus-last-queue-urls")) {
      lastQueueURLs = r["cbus-last-queue-urls"];
    }

    cbus.data.episodeProgresses = r["cbus_episode_progresses"] || [];
    cbus.data.episodeCompletedStatuses = r["cbus_episode_completed_statuses"] || [];
    cbus.data.feedsQNP = r["cbus_feeds_qnp"] || [];

    if (r["cbus_feeds"]) {
      cbus.data.feeds = r["cbus_feeds"].sort(cbus.const.podcastSort);
    } else {
      cbus.data.feeds = [];
    }
    for (let i = 0, l = cbus.data.feeds.length; i < l; i++) {
      cbus.data.feedsCache.push(cbus.data.feeds[i]);
    }
    if (cbus.data.feeds.length > 0) { // there are subscribed feeds
      cbus.ui.tabs.switch({ index: 0 }); // Home tab
    } else { // no subscribed feeds
      cbus.ui.tabs.switch({ index: 3 }); // Explore tab
    }
    cbus.ui.display("feeds");

    fs.readdir(path.join(cbus.const.USERDATA_PATH, "offline_episodes"), function(err, files) {
      for (let i = 0, l = cbus.data.episodesOffline.length; i < l; i++) {
        if (files.indexOf(sha1(cbus.data.episodesOffline[i])) === -1) { // both are arrays of strings
          let episodeURL = cbus.data.episodesOffline[i];
          cbus.data.episodesOffline.splice(i, 1)
          cbus.broadcast.send("offline_episodes_changed", {
            episodeURL: episodeURL
          });
        } else {
          console.log(files)
        }
      }
      localforage.setItem("cbus_episodes_offline", cbus.data.episodesOffline)
    })

    cbus.data.episodesUnsubbed = []

    if (!storedEpisodes && !lastAudioURL) {
      cbus.ui.firstrunContainerElem.classList.add("visible");
    }

    // store globally
    if (storedEpisodes) {
      cbus.data.episodes = storedEpisodes.filter(function(episodeInfo) {
        var feedInfo = cbus.data.getFeedData({ url: episodeInfo.feedURL });
        if (!feedInfo || feedInfo.isUnsubscribed) { return false; }
        return true;
      });
    } else {
      cbus.data.episodes = [];
    }
    if (lastAudioInfo) {
      cbus.data.episodesUnsubbed.push(lastAudioInfo)
    }
    if (lastQueueInfos) {
      for (let i = 0, l = lastQueueInfos.length; i < l; i++) {
        cbus.data.episodesUnsubbed.push(lastQueueInfos[i])
      }
    }
    cbus.data.updateMedias(); // make audio elems and add to DOM
    cbus.ui.display("episodes"); // display the episodes we already have

    if (lastAudioURL) {
      let elem = document.querySelector(`.audios [data-id='${lastAudioURL}']`);
      if (elem) {
        // cbus.audio.setElement(elem, true);
        cbus.audio.setElement(elem);
        if (lastAudioTime) {
          cbus.audio.element.currentTime = lastAudioTime;
          cbus.broadcast.send("audioTick", {
            currentTime: lastAudioTime,
            duration: cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).length
          })
        }
      }
    }

    if (lastQueueURLs) {
      for (let i = 0, l = lastQueueURLs.length; i < l; i++) {
        cbus.audio.enqueue(document.querySelector(`.audios audio[data-id="${ lastQueueURLs[i] }"]`), true)
      }
    }

    cbus.data.update(); // look for any new episodes (takes care of displaying and updateMedias-ing)
  });

  /* start loading popular podcasts */

  cbus.server.getPopularPodcasts((popularPodcastInfos) => {
    console.log(popularPodcastInfos)
    let popularPodcastsElem = document.getElementsByClassName("explore_feeds--popular")[0];
    for (let i = 0, l = popularPodcastInfos.length; i < l; i++) {
      popularPodcastsElem.appendChild(
        cbus.ui.makeFeedElem(popularPodcastInfos[i], i, true)
      );
      cbus.data.feedsCache.push(popularPodcastInfos[i]);
    }
  })

  cbus.broadcast.listen("toggleSubscribe", function(e) {
    console.log(e);

    var completeData = arrayFindByKey(cbus.data.feedsCache, "url", e.data.url)[0];
    var subscribed = !!arrayFindByKey(cbus.data.feeds, "url", e.data.url)[0]

    var direction;
    if (e.data.direction) {
      direction = e.data.direction;
    } else {
      if (subscribed) { // already subscribed
        direction = -1;
      } else { // not subscribed
        direction = 1;
      }
    }

    if (direction === -1) {
      cbus.data.unsubscribeFeed({ url: e.data.url }, true);
    } else {
      // complete required data
      // required keys: image, title, url

      cbus.server.getPodcastInfo(e.data.url, (podcastInfo) => {
        if (podcastInfo) {
          e.data.image = podcastInfo.image;
          e.data.title = podcastInfo.title;
          cbus.data.subscribeFeed(e.data, true);
        }
      });
    }

    if (cbus.data.state.podcastDetailCurrentData.url === e.data.url) {
      if (direction === -1) {
        $(".podcast-detail_control--toggle-subscribe").removeClass("subscribed");
        console.log("removed subscribed class");
      } else {
        $(".podcast-detail_control--toggle-subscribe").addClass("subscribed");
        console.log("added subscribed class");
      }
    }
  });

  /* listen for audio change */

  cbus.broadcast.listen("audioChange", function(e) {
    var element = $("audio audio[data-id='" + e.data.id + "']");

    cbus.broadcast.send("audioTick", {
      currentTime: 0,
      duration: element.duration
    });

    cbus.ui.display("player", e.data);

    // /* extract accent color of feed image and apply to player */
    //
    // cbus.ui.colorify({
    //   image: e.data.feed.image,
    //   element: $(".player")
    // });
    // $(".player").addClass("light-colors");
  });

  /* update audio time */

  let playerTimeNowElem = document.getElementsByClassName("player_time--now")[0];
  let playerTimeTotalElem = document.getElementsByClassName("player_time--total")[0];
  let playerSliderElem = document.getElementsByClassName("player_slider")[0];

  cbus.broadcast.listen("audioTick", function(e) {
    /* slider */
    playerSliderElem.value = Math.round(1000 * e.data.currentTime / e.data.duration) || 0;

    /* time indicator */
    playerTimeNowElem.innerHTML = colonSeparateDuration(e.data.currentTime);
    playerTimeTotalElem.innerHTML = colonSeparateDuration(e.data.duration);

    /* record in localforage so we can resume next time */
    localforage.setItem("cbus-last-audio-time", e.data.currentTime);
  });

  /* open podcast detail when podcast name clicked in episode data */

  document.getElementsByClassName("player_detail_feed-title")[0].onclick = function() {
    cbus.broadcast.send("showPodcastDetail", {
      url: cbus.data.getEpisodeData({ audioElement: cbus.audio.element }).feedURL
    });
  };
});

/* shortly after startup, remove from episodesUnsubbed and feedsQNP episodes/feeds not in queue or now playing */
// setTimeout(function() {
//   var episodesStillNeededURLs = []
//   if (cbus.audio.element) {
//     episodesStillNeededURLs.push(cbus.data.getEpisodeData({audioElement: cbus.audio.element}).url)
//   }
// }, 10000)
<|endoftext|>


<commit_before>/*Constantes*/
//                            stop   |    prevent     | prevent "same element"
//                          bubbling | default action | event handlers
//
//return false                 Yes           Yes             No
//preventDefault()             No            Yes             No
//stopPropagation()            Yes           No              No
//stopImmediatePropagation()   Yes           No              Yes

var wsAnimationTime = 200;

$(document).on("keydown", function(e){
//	var evt = (evt) ? evt : ((event) ? event : null);
//	var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
	if ((e.keyCode == 13) &&
		(e.target.type=="text"))  {
		return false;
	}
	if ((e.keyCode == 8) &&
		(e.target.type=="select-one" ||
		 e.target.type=="radio" ||
		 e.target.type=="submit" ||
		 e.target.type=="checkbox"))  {
			return false;
	}
});

String.prototype.replaceAll = function(target, replacement) {
  return this.split(target).join(replacement);
};

dbsfaces = {
	CSS : {
		MODIFIER : {
			CLOSABLE : " -closable ",
			CLOSED : " -closed ",
			SELECTED : " -selected ",
			SELECTABLE : " -selectable ",
			TITLE : " -title ",
			LABEL : " -label ",
			ICON : " -icon ",
			ICONCLOSE : " -iconclose ",
			DISABLED : " -disabled "
		}
	},

	ID: {
		DIALOG: "dialog",
		INPUTTEXT: "inputText"
	},

	EVENT: {
		ON_AJAX_BEGIN: "dbs_ON_AJAX_BEGIN",
		ON_AJAX_COMPLETE: "dbs_ON_AJAX_COMPLETE",
		ON_AJAX_SUCCESS: "dbs_ON_AJAX_SUCESS",
		ON_SUGGESTION_REQUEST: "dbs_ON_SUGGESTION_REQUEST",
		ON_SUGGESTION_RESPONSE: "dbs_ON_SUGGESTION_RESPONSE",
		ON_SUGGESTION_ACCEPTED: "dbs_ON_SUGGESTION_ACCEPTED",
		ON_ROW_SELECTED: "dbs_ON_ROW_SELECTED"
	}

}

var wAjaxTimeout;

dbsfaces.sound = {
	beep : function(){
		$("#dbs_beep").remove();
		$("body").append('<audio id="dbs_beep" src="sound/alert.mp3" preload autoplay/>');
//		$("body").append('<embed id="dbs_beep" src="sound/alert.mp3" showcontrols="false" hidden="true" autostart="true" loop="false" />');
	}
}

dbsfaces.ui = {
	centerVertical : function(pId){
		var xH = $(pId).outerHeight() / 2;
		$(pId).css("margin-top",  -xH + "px")
		      .css("top", "50%")
		      .css("position", "absolute");
	},

	/*Centraliza via código. Procure utilizar o centralização por CSS*/
	centerWindow : function (pMinWidth, pMinHeight, pElement){
			var xParentWidth;
			var xParentHeight;
			if (window.innerWidth<pMinWidth){
				xParentWidth = pMinWidth;
			}else{
				xParentWidth = window.innerWidth;
			}
			if (window.innerHeight<pMinHeight){
				xParentHeight = pMinHeight;
			}else{
				xParentHeight = window.innerHeight;
			}
		    xHCenter = (xParentWidth - $(pElement).outerWidth()) / 2;
		    xVCenter = (xParentHeight - $(pElement).outerHeight()) / 2;
			$(pElement).css("left", xHCenter + "px")
					   .css("top", xVCenter + "px")
					   .css("position", "fixed");
	},

	/*Centaliza todos os elementos que possuem a classe dbsAlignCenterThis*/
	centerWindows : function(pMinWidth, pMinHeight, pSelector){
		$(pSelector).each(function(index, value) {
			dbsfaces.util.centerWindow(pMinWidth, pMinHeight, this);
		});
	},

	/*Exibe a imagem de que indica que está aguardando o recebimento dos dados*/
	showLoading : function(pId, pStatus){
		var xId = "dbs_ajaximg_" + $.trim(pId);
		if ($("#" + xId).length > 0){
	    	$("#" + xId).remove();
		}
	    if (pStatus){
	        $('body').append("");
	    }
	},

	showLoadingError : function(pId){
		var xId = "dbs_ajaximg_" + $.trim(pId);
		$("#" + xId).css("background-color", "rgba(255,255,180,0.8)");
		$("#" + xId).fadeOut(2000, function(){
			$("#" + xId).remove();
			$("div .-loading").remove();
		});
	},

	getRectangle : function(obj) {
	   var off = obj.offset();

	   return {
	          top: off.top,
	          left: off.left,
	          height: obj.outerHeight(),
	          width: obj.outerWidth()
	   };
	},

	isInsideRectangle : function(pX, pY, pRect) {
        if ((pX > pRect.left && pX < (pRect.left + pRect.width))
            && (pY > pRect.top && pY < (pRect.top + pRect.height))){
        	return true;
        }else{
	        return false;
        }
	},

	isOverlappingRectagle : function(pRectA, pRectB) {
		if (dbsfaces.ui.isInsideRectangle(pRectA.left, pRectA.top, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left + pRectA.width, pRectA.top, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left, pRectA.top + pRectA.height, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left + pRectA.width, pRectA.top + pRectA.height, pRectB)){
			return true;
		}else{
			return false;
		}
	},

	//Captura evento ajax dbsoft
	captureAjax : function(pSelector){
//		console.log("CAPTURE " + pSelector);
		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_BEGIN);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_BEGIN, function(e){
			dbsfaces.ui.showLoading("main",true);
		});
		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_COMPLETE);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_COMPLETE, function(e){
			//Reinicia a contagem do timeout a cada complete, já que existe respostas ajax em andamento
			window.clearTimeout(wAjaxTimeout);
			wAjaxTimeout = window.setTimeout(function(e){
				dbsfaces.ui.showLoadingError("main");
			}, 1000); //Time de delay para efetuar a chamada acima(showLoadingError). A chamada será cancelada em caso de sucesso.
		});

		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_SUCCESS);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_SUCCESS, function(e){
			window.clearTimeout(wAjaxTimeout); //Cancela o timeout definido no evento COMPLETE, cancelando a respectiva chamada ao showLoadingError.
			dbsfaces.ui.showLoading("main",false);
		});
	},

	focusOnFirstInput: function(pContainer){
		//Seta foco no primeiro campo de input
		var xEle = pContainer.find("input:first");
		//Se não achou input, procura por combobox.
		if (xEle.length == 0 ){
			xEle = pContainer.find("select:first");
			//Se não achou input, procura por botão.
			if (xEle.length == 0 ){
				xEle = pContainer.find("button:first");
			}
		}
		if (xEle.length != 0 ){
			xEle.focus();
		}
	}
}

dbsfaces.util = {
	/*Verifica se elemento existe*/
	exists: function(pId){
		if(!dbsfaces.util.isEmpty(pId)){
			if ($(pId).length>0){
				return true;
			}else{
				return false;
			}
		}else{
			return false;
		}
	},

	//Retorna vazio se for nulo
	getNotNull: function(pValue, pDefaultValue){
		if(pValue == null){
			return pDefaultValue;
		}
	},

	//Verifica se � nulo ou vazio
	isEmpty: function(pValue){
		if(pValue == null){
			return true;
		}
		if(pValue == ''){
			return true;
		}
		return false;
	},

	/*dispara evento para o elemento informado*/
	trigger: function (pEventName, pId){
		if (dbsfaces.util.exists(pId) &&
			!dbsfaces.util.isEmpty(pEventName)){
				var xEvent = $.Event(pEventName);
				//Dispara evento depois de fechar
				$(pId).trigger(xEvent);
				return xEvent;
		}else{
			alert('Parametros inválidos! pId=' + pId + ' pEventName=' + pEventName + ' dbsFaces.trigger');
			return false;
		}
	}
}

dbsfaces.util.isiOS = function(){
    return (
        //Detect iPhone
        (navigator.platform.indexOf("iPhone") != -1) ||
        //Detect iPad
        (navigator.platform.indexOf("iPad") != -1)
    );
}

dbsfaces.util.isTablet = function(){
    return dbsfaces.util.isiOS();
}

dbsfaces.util.jsid = function(pClientId){
	return pClientId.replace(/:/g,"\\:");
}

dbsfaces.date = {
	isDate:function(pYear, pMonth, pDay, pHour, pSeconds, pMilliseconds){
		pMonth = pMonth - 1;
		var xD =  new Date(pYear, pMonth, pDay, pHour, pSeconds, pMilliseconds);
		if (xD.getDate() != pDay){
			return "";
		}
		if (xD.getMonth() != pMonth){
			return "";
		}
		if (xD.getFullYear() != pYear){
			return "";
		}
		return xD;
	}
}

dbsfaces.number = {
	isNumber: function(pVal){
		return !isNaN(parseFloat(pVal)) && isFinite(pVal);
	}
};

//Monitora evento ajax recebido e dispara evento dbsoft
dbsfaces.onajax = function(e){
	if ($(e.source).length == 0){
		return;
	}
	if (e.status == "begin"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_BEGIN);
	}else if (e.status == "complete"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_COMPLETE);
	}else if (e.status == "success"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_SUCCESS);
	}
};

$.fn.focusNextInputField = function() {
    return this.each(function() {
        var fields = $(this).parents('form:eq(0),body').find('button,input,textarea,select');
        var index = fields.index( this );
        if ( index > -1 && ( index + 1 ) < fields.length ) {
            fields.eq( index).focus();
        }
        return false;
    });
};
<commit_msg>Ignora e.keyCode == 46 no checkbox<commit_after>/*Constantes*/
//                            stop   |    prevent     | prevent "same element"
//                          bubbling | default action | event handlers
//
//return false                 Yes           Yes             No
//preventDefault()             No            Yes             No
//stopPropagation()            Yes           No              No
//stopImmediatePropagation()   Yes           No              Yes

var wsAnimationTime = 200;

$(document).on("keydown", function(e){
//	var evt = (evt) ? evt : ((event) ? event : null);
//	var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
	if ((e.keyCode == 13) &&
		(e.target.type=="text"))  {
		return false;
	}
	if ((e.keyCode == 8
	  || e.keyCode == 46) &&
		(e.target.type=="select-one" ||
		 e.target.type=="radio" ||
		 e.target.type=="submit" ||
		 e.target.type=="checkbox"))  {
			return false;
	}
});

String.prototype.replaceAll = function(target, replacement) {
  return this.split(target).join(replacement);
};

dbsfaces = {
	CSS : {
		MODIFIER : {
			CLOSABLE : " -closable ",
			CLOSED : " -closed ",
			SELECTED : " -selected ",
			SELECTABLE : " -selectable ",
			TITLE : " -title ",
			LABEL : " -label ",
			ICON : " -icon ",
			ICONCLOSE : " -iconclose ",
			DISABLED : " -disabled "
		}
	},

	ID: {
		DIALOG: "dialog",
		INPUTTEXT: "inputText"
	},

	EVENT: {
		ON_AJAX_BEGIN: "dbs_ON_AJAX_BEGIN",
		ON_AJAX_COMPLETE: "dbs_ON_AJAX_COMPLETE",
		ON_AJAX_SUCCESS: "dbs_ON_AJAX_SUCESS",
		ON_SUGGESTION_REQUEST: "dbs_ON_SUGGESTION_REQUEST",
		ON_SUGGESTION_RESPONSE: "dbs_ON_SUGGESTION_RESPONSE",
		ON_SUGGESTION_ACCEPTED: "dbs_ON_SUGGESTION_ACCEPTED",
		ON_ROW_SELECTED: "dbs_ON_ROW_SELECTED"
	}

}

var wAjaxTimeout;

dbsfaces.sound = {
	beep : function(){
		$("#dbs_beep").remove();
		$("body").append('<audio id="dbs_beep" src="sound/alert.mp3" preload autoplay/>');
//		$("body").append('<embed id="dbs_beep" src="sound/alert.mp3" showcontrols="false" hidden="true" autostart="true" loop="false" />');
	}
}

dbsfaces.ui = {
	centerVertical : function(pId){
		var xH = $(pId).outerHeight() / 2;
		$(pId).css("margin-top",  -xH + "px")
		      .css("top", "50%")
		      .css("position", "absolute");
	},

	/*Centraliza via código. Procure utilizar o centralização por CSS*/
	centerWindow : function (pMinWidth, pMinHeight, pElement){
			var xParentWidth;
			var xParentHeight;
			if (window.innerWidth<pMinWidth){
				xParentWidth = pMinWidth;
			}else{
				xParentWidth = window.innerWidth;
			}
			if (window.innerHeight<pMinHeight){
				xParentHeight = pMinHeight;
			}else{
				xParentHeight = window.innerHeight;
			}
		    xHCenter = (xParentWidth - $(pElement).outerWidth()) / 2;
		    xVCenter = (xParentHeight - $(pElement).outerHeight()) / 2;
			$(pElement).css("left", xHCenter + "px")
					   .css("top", xVCenter + "px")
					   .css("position", "fixed");
	},

	/*Centaliza todos os elementos que possuem a classe dbsAlignCenterThis*/
	centerWindows : function(pMinWidth, pMinHeight, pSelector){
		$(pSelector).each(function(index, value) {
			dbsfaces.util.centerWindow(pMinWidth, pMinHeight, this);
		});
	},

	/*Exibe a imagem de que indica que está aguardando o recebimento dos dados*/
	showLoading : function(pId, pStatus){
		var xId = "dbs_ajaximg_" + $.trim(pId);
		if ($("#" + xId).length > 0){
	    	$("#" + xId).remove();
		}
	    if (pStatus){
	        $('body').append("");
	    }
	},

	showLoadingError : function(pId){
		var xId = "dbs_ajaximg_" + $.trim(pId);
		$("#" + xId).css("background-color", "rgba(255,255,180,0.8)");
		$("#" + xId).fadeOut(2000, function(){
			$("#" + xId).remove();
			$("div .-loading").remove();
		});
	},

	getRectangle : function(obj) {
	   var off = obj.offset();

	   return {
	          top: off.top,
	          left: off.left,
	          height: obj.outerHeight(),
	          width: obj.outerWidth()
	   };
	},

	isInsideRectangle : function(pX, pY, pRect) {
        if ((pX > pRect.left && pX < (pRect.left + pRect.width))
            && (pY > pRect.top && pY < (pRect.top + pRect.height))){
        	return true;
        }else{
	        return false;
        }
	},

	isOverlappingRectagle : function(pRectA, pRectB) {
		if (dbsfaces.ui.isInsideRectangle(pRectA.left, pRectA.top, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left + pRectA.width, pRectA.top, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left, pRectA.top + pRectA.height, pRectB) ||
			dbsfaces.ui.isInsideRectangle(pRectA.left + pRectA.width, pRectA.top + pRectA.height, pRectB)){
			return true;
		}else{
			return false;
		}
	},

	//Captura evento ajax dbsoft
	captureAjax : function(pSelector){
//		console.log("CAPTURE " + pSelector);
		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_BEGIN);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_BEGIN, function(e){
			dbsfaces.ui.showLoading("main",true);
		});
		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_COMPLETE);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_COMPLETE, function(e){
			//Reinicia a contagem do timeout a cada complete, já que existe respostas ajax em andamento
			window.clearTimeout(wAjaxTimeout);
			wAjaxTimeout = window.setTimeout(function(e){
				dbsfaces.ui.showLoadingError("main");
			}, 1000); //Time de delay para efetuar a chamada acima(showLoadingError). A chamada será cancelada em caso de sucesso.
		});

		$(pSelector).off(dbsfaces.EVENT.ON_AJAX_SUCCESS);
		$(pSelector).on(dbsfaces.EVENT.ON_AJAX_SUCCESS, function(e){
			window.clearTimeout(wAjaxTimeout); //Cancela o timeout definido no evento COMPLETE, cancelando a respectiva chamada ao showLoadingError.
			dbsfaces.ui.showLoading("main",false);
		});
	},

	focusOnFirstInput: function(pContainer){
		//Seta foco no primeiro campo de input
		var xEle = pContainer.find("input:first");
		//Se não achou input, procura por combobox.
		if (xEle.length == 0 ){
			xEle = pContainer.find("select:first");
			//Se não achou input, procura por botão.
			if (xEle.length == 0 ){
				xEle = pContainer.find("button:first");
			}
		}
		if (xEle.length != 0 ){
			xEle.focus();
		}
	}
}

dbsfaces.util = {
	/*Verifica se elemento existe*/
	exists: function(pId){
		if(!dbsfaces.util.isEmpty(pId)){
			if ($(pId).length>0){
				return true;
			}else{
				return false;
			}
		}else{
			return false;
		}
	},

	//Retorna vazio se for nulo
	getNotNull: function(pValue, pDefaultValue){
		if(pValue == null){
			return pDefaultValue;
		}
	},

	//Verifica se � nulo ou vazio
	isEmpty: function(pValue){
		if(pValue == null){
			return true;
		}
		if(pValue == ''){
			return true;
		}
		return false;
	},

	/*dispara evento para o elemento informado*/
	trigger: function (pEventName, pId){
		if (dbsfaces.util.exists(pId) &&
			!dbsfaces.util.isEmpty(pEventName)){
				var xEvent = $.Event(pEventName);
				//Dispara evento depois de fechar
				$(pId).trigger(xEvent);
				return xEvent;
		}else{
			alert('Parametros inválidos! pId=' + pId + ' pEventName=' + pEventName + ' dbsFaces.trigger');
			return false;
		}
	}
}

dbsfaces.util.isiOS = function(){
    return (
        //Detect iPhone
        (navigator.platform.indexOf("iPhone") != -1) ||
        //Detect iPad
        (navigator.platform.indexOf("iPad") != -1)
    );
}

dbsfaces.util.isTablet = function(){
    return dbsfaces.util.isiOS();
}

dbsfaces.util.jsid = function(pClientId){
	return pClientId.replace(/:/g,"\\:");
}

dbsfaces.date = {
	isDate:function(pYear, pMonth, pDay, pHour, pSeconds, pMilliseconds){
		pMonth = pMonth - 1;
		var xD =  new Date(pYear, pMonth, pDay, pHour, pSeconds, pMilliseconds);
		if (xD.getDate() != pDay){
			return "";
		}
		if (xD.getMonth() != pMonth){
			return "";
		}
		if (xD.getFullYear() != pYear){
			return "";
		}
		return xD;
	}
}

dbsfaces.number = {
	isNumber: function(pVal){
		return !isNaN(parseFloat(pVal)) && isFinite(pVal);
	}
};

//Monitora evento ajax recebido e dispara evento dbsoft
dbsfaces.onajax = function(e){
	if ($(e.source).length == 0){
		return;
	}
	if (e.status == "begin"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_BEGIN);
	}else if (e.status == "complete"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_COMPLETE);
	}else if (e.status == "success"){
		$(e.source).trigger(dbsfaces.EVENT.ON_AJAX_SUCCESS);
	}
};

$.fn.focusNextInputField = function() {
    return this.each(function() {
        var fields = $(this).parents('form:eq(0),body').find('button,input,textarea,select');
        var index = fields.index( this );
        if ( index > -1 && ( index + 1 ) < fields.length ) {
            fields.eq( index).focus();
        }
        return false;
    });
};
<|endoftext|>


<commit_before>/*
 * Angular Trianglify Animate
 * github: https://github.com/machei/angular-trianglify-animate
 * @author: machei
 * @thanks: grohlf & empathetic-alligator
 */

function scale(valueIn, baseMin, baseMax, limitMin, limitMax) {
    return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin;
}

angular.module('moduleTrianglifyAnimate', [])
.constant('configTrianglifyAnimate', {
	speed:1,
	vectorX: 1,
	vectorY: 1,
	baseMax: 0,
	baseMin: 500,
	theta: 0.4,
	pathPassSymbols : 'MZLHmzlh'
})
.directive("ngTrianglifyAnimate", ["$compile", function($compile) {
	return {
		restrict:'EA',
		scope:{
			interval: '='
		},
		controller: ['$scope', '$element', '$attrs', '$interval', 'configTrianglifyAnimate', function ($scope, $element, $attrs, $interval, configTrianglifyAnimate) {
			// Replace img with svg
			if($element[0].tagName === "IMG" && window.File && window.FileList && window.FileReader){
				var $e = $element[0] , $p = $element[0].parentNode;
				var xhr = new XMLHttpRequest();
				xhr.open("GET", $e.src, false);
				xhr.responseType = "xml";
				function response(e){
					var parser, xmlDoc;
					if (window.XMLHttpRequest){ // Chorme, Firefox, Opera
						parser=new DOMParser();
						xmlDoc = parser.parseFromString(e.target.response,"text/xml");
					}else{ // IE
						xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
						xmlDoc.async=false;
						xmlDoc.loadXML(e.target.response);
					}

					svg = xmlDoc.getElementsByTagName("svg")[0];
					svg.setAttribute('ng-trianglify-animate','');
					for(var i=0; i<$e.attributes.length; i++){
						svg.setAttribute($e.attributes[i].nodeName,$e.attributes[i].value);
					}
					svg = angular.element(svg);
					$element.replaceWith(svg);
					$compile(svg)($scope);
					$element = svg;
				}
				xhr.onload = response; // error on firefox
				xhr.send();
				return true;
			}

			// Attrs
			angular.forEach(['speed', 'vectorX', 'vectorY', 'baseMax', 'baseMin', 'theta'], function( key, index ) {
				$scope[key] = angular.isDefined($attrs[key]) ? (index < 6 ? $attrs[key] : $scope.$parent.$eval($attrs[key])) : configTrianglifyAnimate[key];
			});

			// Init Shapes
			var polygons = $element[0].getElementsByTagName('polygon');
			var polys = [];
			for(var i=0; i<polygons.length; i++){
				// Chrome&Firefox&Opera works except IE 11:
				polys[i] = polygons[i].points;
				// For IE:
				//var d = polygons[i].getAttribute('points').split(' ');
				//for(var q=0; q<d.length; q++){
				//	var point = d[q].split(',')
				//	polys[i] = {x:point[0], y:point[1]};
				//}
			}

			var el_paths = $element[0].getElementsByTagName('path');
			var paths = [], path;

			for(var i=0; i<el_paths.length; i++){
				paths[i] = el_paths[i].pathSegList;
			}

			$scope.polys = polys;
			$scope.paths = paths;
			$scope.theta = 0;

			var animate = function(){

				// polygons
				// IE11 : F12 tools do not currently support extensive Scalable Vector Graphics (SVG) debugging, but several console messages are displayed to help debug SVG code.

				for(var i = 0; i < $scope.polys.length; i++) {
					$poly = $scope.polys[i];
					for(var q=0; q < $poly.length; q++){ // .numberOfItems
						$poly[q].y = $poly[q].y + Math.sin($scope.theta + scale($poly[q].x, 0, 500, 0, 2 * Math.PI)) * 0.5;
					}
				}

				// path
				for(var i = 0; i < $scope.paths.length; i++) {
					$path = $scope.paths[i];
					for(var q=0; q<$path.length; q++){
						if(configTrianglifyAnimate.pathPassSymbols.indexOf($path[q].pathSegTypeAsLetter) > -1){
							$path[q].y = $path[q].y + Math.sin($scope.theta + scale($path[q].x, 0, 500, 0, 2 * Math.PI)) * 0.5;
						}else{
							//console.log($path[q].pathSegTypeAsLetter);
						}
					}
				}

				// todo: circle, rect, ellipse, line, polyline
				$scope.theta += 0.04;
			};
			$scope.animate = $interval(function(){animate()}, 10/$scope.speed, false);

		}]
};
}]);<commit_msg>updated shapes and support browser<commit_after>/*
 * Angular Trianglify Animate
 * github: https://github.com/machei/angular-trianglify-animate
 * @author: machei
 * @thanks: grohlf & empathetic-alligator
 */

function scale(valueIn, baseMin, baseMax, limitMin, limitMax) {
    return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin;
}

angular.module('moduleTrianglifyAnimate', [])
.constant('configTrianglifyAnimate', {
	speed:1,
	vectorX: 1,
	vectorY: 1,
	baseMax: 0,
	baseMin: 500,
	theta: 0.4,
	pathPassSymbols : 'MZLHmzlh'
})
.directive("ngTrianglifyAnimate", ["$compile", function($compile) {
	return {
		restrict:'EA',
		scope:{
			interval: '='
		},
		controller: ['$scope', '$element', '$attrs', '$interval', 'configTrianglifyAnimate', function ($scope, $element, $attrs, $interval, configTrianglifyAnimate) {
			// Replace img with svg
			if($element[0].tagName === "IMG" && window.File && window.FileList && window.FileReader){
				var $e = $element[0] , $p = $element[0].parentNode;
				var xhr = new XMLHttpRequest();
				xhr.open("GET", $e.src, false);
				xhr.responseType = "xml";
				function response(e){
					var parser, xmlDoc;
					if (window.XMLHttpRequest){ // Chorme, Firefox, Opera
						parser=new DOMParser();
						xmlDoc = parser.parseFromString(e.target.response,"text/xml");
					}else{ // IE
						xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
						xmlDoc.async=false;
						xmlDoc.loadXML(e.target.response);
					}

					svg = xmlDoc.getElementsByTagName("svg")[0];
					svg.setAttribute('ng-trianglify-animate','');
					for(var i=0; i<$e.attributes.length; i++){
						svg.setAttribute($e.attributes[i].nodeName,$e.attributes[i].value);
					}
					svg = angular.element(svg);
					$element.replaceWith(svg);
					$compile(svg)($scope);
					$element = svg;
				}
				xhr.onload = response; // error on firefox
				xhr.send();
				return true;
			}

			// Attrs
			angular.forEach(['speed', 'vectorX', 'vectorY', 'baseMax', 'baseMin', 'theta'], function( key, index ) {
				$scope[key] = angular.isDefined($attrs[key]) ? (index < 6 ? $attrs[key] : $scope.$parent.$eval($attrs[key])) : configTrianglifyAnimate[key];
			});

			//** Init Shapes **//

			// Chrome&Firefox&Opera works except IE 11:

			// For IE:
			//var d = polygons[i].getAttribute('points').split(' ');
			//for(var q=0; q<d.length; q++){
			//	var point = d[q].split(',')
			//	polys[i] = {x:point[0], y:point[1]};
			//}

			// Shape <polygon>
			var polygons = $element[0].getElementsByTagName('polygon');
			for(var i=0, polys=[]; i<polygons.length; i++) polys[i] = polygons[i].points;

			// Shape <path>
			var el_paths = $element[0].getElementsByTagName('path');
			for(var i=0, paths=[]; i<el_paths.length; i++) paths[i] = el_paths[i].pathSegList;

			// Shape <circle>
			var el_circle = $element[0].getElementsByTagName('circle');
			for(var i=0, circles=[]; i<el_circle.length; i++) circles[i] = {'x':el_circle[i].cx,'y':el_circle[i].cy,'r':el_circle[i].r};

			// Shape <rect>
			var el_rect = $element[0].getElementsByTagName('rect');
			for(var i=0, rects=[]; i<el_rect.length; i++) rects[i] = {'x':el_rect[i].x, 'y':el_rect[i].y, 'width':el_rect[i].width, 'height':el_rect[i].height};

			// Shape <ellipse>
			var el_ellipse = $element[0].getElementsByTagName('ellipse');
			for(var i=0, ellipses=[]; i<el_ellipse.length; i++) ellipses[i] = {'x':el_ellipse[i].rx, 'y':el_ellipse[i].ry};

			// Shape <line>
			var el_line = $element[0].getElementsByTagName('line');
			for(var i=0, lines=[]; i<el_line.length; i++) lines[i] = {'x1':el_line[i].x1, 'y1':el_line[i].y1, 'x2':el_line[i].x2, 'y2':el_line[i].y2};

			// Shape <polyline>
			var el_polyline = $element[0].getElementsByTagName('polyline');
			for(var i=0, polylines=[]; i<el_polyline.length; i++) polylines[i] = el_polyline[i].points;

			angular.extend($scope, {'polys':polys, 'paths':paths, 'circles':circles, 'rects':rects, 'ellipses':ellipses, 'lines':lines, 'polylines':polylines});
			$scope.theta = 0;

			var animate = function(){

				// polygons
				// Problem IE11 : F12 tools do not currently support extensive Scalable Vector Graphics (SVG) debugging, but several console messages are displayed to help debug SVG code.

				// Shape <polygon>
				for(var i = 0, $poly; i < $scope.polys.length; i++)
					for(var q=0, $poly = $scope.polys[i], $item; q < $poly.numberOfItems; q++)
						($item=$poly.getItem(q)).y = $item.y + Math.sin($scope.theta + scale($item.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				// Shape <path>
				for(var i = 0, $path; i < $scope.paths.length; i++)
					for(var q=0, $path = $scope.paths[i], $item; q<$path.numberOfItems; q++)
						if(configTrianglifyAnimate.pathPassSymbols.indexOf(($item = $path.getItem(q)).pathSegTypeAsLetter) > -1)
							$item.y = $item.y + Math.sin($scope.theta + scale($item.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				// Shape <circle>
				for(var i = 0, $circle; i < $scope.circles.length; i++)
					($circle = $scope.circles[i]).y = $circle.y + Math.sin($scope.theta + scale($circle.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				// Shape <rect>
				for(var i = 0, $rect; i < $scope.rects.length; i++)
					($rect = $scope.rects[i]).y = $rect.y + Math.sin($scope.theta + scale($rect.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				// Shape <ellipse>
				for(var i = 0, $ellipse; i < $scope.ellipses.length; i++)
					($ellipse = $scope.ellipses[i]).y = $ellipse.y + Math.sin($scope.theta + scale($ellipse.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				// Shape <line>
				for(var i = 0, $line; i < $scope.lines.length; i++) {
					($line = $scope.lines[i]).y1 = $line.y1 + Math.sin($scope.theta + scale($line.x1, 0, 500, 0, 2 * Math.PI)) * 0.5;
					$line.y2 = $line.y2 + Math.sin($scope.theta + scale($line.x2, 0, 500, 0, 2 * Math.PI)) * 0.5;
				}

				// Shape <polyline>
				for(var i = 0, $polyline; i < $scope.polylines.length; i++)
					for(var q=0, $polyline = $scope.polylines[i], $item; q < $polyline.numberOfItems; q++)
						($item=$polyline.getItem(q)).y = $item.y + Math.sin($scope.theta + scale($item.x, 0, 500, 0, 2 * Math.PI)) * 0.5;

				$scope.theta += 0.04;
			};
			$scope.animate = $interval(function(){animate()}, 10/$scope.speed, false);

		}]
};
}]);<|endoftext|>


<commit_before>'use strict';

/*
 * Auth Services
 * Sets Nav, Session and Build as global page variables.
 */

angular.module('rcAuth.UserSession', [])
    .service('UserSession', [function() {

    // Create a copy of this session object
    var self = this;

    // Create a varable to hold the logged in user session
    // False by default because no user is logged in yet
    self.user = false;

    // Validate that an object is a valid user object
    self.validateUser = function(opt) {
        return (typeof(opt) !== 'undefined' &&
                typeof(opt.id) !== 'undefined' &&
                typeof(opt.displayName) !== 'undefined' &&
                typeof(opt.email) !== 'undefined' &&
                typeof(opt.roles) !== 'undefined' &&
                typeof(opt.apiKey) !== 'undefined' &&
                typeof(opt.apiToken) !== 'undefined');
    };

    // Create a user session
    self.create = function(opt) {
        // Validate that the sent object is a valid user
        if(self.validateUser(opt)) {
            // Set the user session
            self.user = opt;
            return self.user;
        } else {
            return false;
        }
    };

    // Destryo the current session object
    self.destroy = function() {
        self.user = false;
        return true;
    };

    // Return a copy of the user object
    // If no user is logged in this will return false
    self.get = function() {
        return (!self.user) ? false : angular.copy(self.user);
    };

    // Safly return the User Id
    self.id = function() {
        return (!self.user.id) ? false : angular.copy(self.user.id);
    };

    // Safly return the User Display Name
    self.displayName = function() {
        return (!self.user.displayName) ? false : angular.copy(self.user.displayName);
    };

    // Safly return the User Email
    self.email = function() {
        return (!self.user.email) ? false : angular.copy(self.user.email);
    };

    // Safly return the User Role Object
    self.roles = function() {
        return (!self.user.roles) ? false : angular.copy(self.user.roles);
    };

    // Return public methods
    return {
            create : self.create,
            destroy : self.destroy,
            get : self.get,
            id : self.id,
            displayName : self.displayName,
            email : self.email,
            roles : self.roles
        };

    }]);
<commit_msg>Adjusted user to hold the api key and token pair.<commit_after>'use strict';

/*
 * Auth Services
 * Sets Nav, Session and Build as global page variables.
 */

angular.module('rcAuth.UserSession', [])
    .service('UserSession', [function() {

    // Create a copy of this session object
    var self = this;

    // Create a varable to hold the logged in user session
    // False by default because no user is logged in yet
    self.user = false;

    // Validate that an object is a valid user object
    self.validateUser = function(user, session) {
        return (typeof(user) !== 'undefined' &&
                typeof(user.id) !== 'undefined' &&
                typeof(user.displayName) !== 'undefined' &&
                typeof(user.email) !== 'undefined' &&
                typeof(user.roles) !== 'undefined' &&
                typeof(user.apiKey) !== 'undefined' &&
                typeof(user.apiToken) !== 'undefined');
    };

    // Create a user session
    self.create = function(user) {
        // Validate that the sent object is a valid user
        if(self.validateUser(user)) {
            // Set the user session
            self.user = user;
            return self.user;
        } else {
            return false;
        }
    };

    // Destryo the current session object
    self.destroy = function() {
        self.user = false;
        return true;
    };

    // Return a copy of the user object
    // If no user is logged in this will return false
    self.get = function() {
        return (!self.user) ? false : angular.copy(self.user);
    };

    // Safly return the User Id
    self.id = function() {
        return (!self.user.id) ? false : angular.copy(self.user.id);
    };

    // Safly return the User Display Name
    self.displayName = function() {
        return (!self.user.displayName) ? false : angular.copy(self.user.displayName);
    };

    // Safly return the User Email
    self.email = function() {
        return (!self.user.email) ? false : angular.copy(self.user.email);
    };

    // Safly return the User Role Object
    self.roles = function() {
        return (!self.user.roles) ? false : angular.copy(self.user.roles);
    };

    // Return public methods
    return {
            create : self.create,
            destroy : self.destroy,
            get : self.get,
            id : self.id,
            displayName : self.displayName,
            email : self.email,
            roles : self.roles
        };

    }]);
<|endoftext|>


<commit_before>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
(function() {
    'use strict';

    var DIR         = __dirname + '/',
        os          = require('os'),
        crypto      = require('crypto'),
        fs          = require('fs'),
        path        = require('path'),

        mkdirp      = require('mkdirp'),
        ischanged   = require('ischanged'),
        Util        = require('util-io'),
        ponse       = require('ponse'),

        WIN         = process.platform === 'win32',

        MinFolder   = getDir() || DIR + 'min/';

    module.exports  = minify;

    function getModule(name) {
        return require(DIR + name);
    }

    function optimizeData(params, callback) {
        var module, p = params;

        switch(p.ext) {
            case '.js':
                module = getModule('js');
                module._uglifyJS(p.data, callback);
                break;

            case '.html':
                module = getModule('html');
                module.htmlMinify(p.data, callback);
                break;

            case '.css':
                module = getModule('css');
                module._cleanCSS(p.data, callback);
                break;
        }
    }

    function minify(name, options, callback) {
        var isChanged, isExist, ret,
            isObject    = Util.isObject(name),
            exec        = Util.exec,
            nameMin     = getName(name);

        if (!callback)
            callback = options;

        if (!options && !callback)
            ret = middle.bind(null, name);
        else if (isObject) {
            optimizeData(name, callback);
        } else {
            isChanged   = exec.with(ischanged, name),
            isExist     = exec.with(fs.lstat, nameMin);

            exec.parallel([isChanged, isExist], function(error, changed, exists) {
                if (changed || !exists)
                    optimize(name, options, callback);
                else
                    if (options.returnName)
                        callback(null, nameMin);
                    else
                        fs.readFile(nameMin, 'utf8', callback);
            });
        }

        return ret;
    }

    function getDir() {
        var dir;

        if (os.tmpdir) {
            dir     = os.tmpdir();
            dir     += '/minify';

            if (!WIN)
                dir += '/' + process.getuid();

            dir     += '/';
        }

        return dir;
    }

    function makeDir(callback) {
        var ANY_MASK    = 0,
            umask       = process.umask(ANY_MASK);

        mkdirp(MinFolder, function(error) {
            process.umask(umask);

            if (error && error.code === 'EEXIST')
                callback();
            else
                callback(error);
        });
    }

    function middle(options, req, res, next) {
        var isMinify, dir, is, isFunction,
            name        = req.path,
            isExt       = Util.checkExt(name, ['js', 'css', 'html']);

        Util.checkArgs([options], ['options']);

        is              = options.is;
        dir             = options.dir || './';

        isFunction      = Util.isFunction(is);
        name            = path.join(dir, req.path);

        if (isFunction)
            isMinify    = is();
        else
            isMinify    = is || Util.isUndefined(is);

        if (!isExt || !isMinify)
            next();
        else
            minify(name, {
                log         : options.log,
                returnName  : true
            }, function(error, name) {
                if (error)
                    next();
                else
                    ponse.sendFile({
                        request: req,
                        response: res,
                        name: name,
                        gzip: true,
                        cache:true,
                    });
            });
    }

    /**
     * function minificate js,css and html files
     *
     * @param files     -   js, css or html file path
     * @param options   -   object contain main options
     */
    function optimize(file, options, callback) {
        if (!callback)
            callback = options;

        Util.checkArgs(arguments, ['file', 'callback']);

        makeDir(function(error) {
            var name, basename, msg,
                islog   = options.log,
                isObj   = Util.isObject(file);

            if (error)
                log(error, islog);

            if (isObj)
                name    = Object.keys(file)[0];
            else
                name    = file;

            basename    = path.basename(name);
            msg         = 'minify: reading file ' + basename + '...';

            log(msg, islog);

            fs.readFile(name, 'utf8', function(error, data) {
                if (error)
                    callback(error);
                else
                    onDataRead(file, data, options, callback);
            });
        });
    }

   /**
    * Processing of files
    * @param fileData {name, data}
    */
    function onDataRead(filename, data, options, callback) {
        var ext, minFileName,
            readFilesCount  = 0,
            isLog           = options.log,
            returnName      = options.returnName,
            basename        = path.basename(filename);

        log('minify: file ' + basename + ' read', isLog);

        ext         = path.extname(filename);
        minFileName = getName(filename, ext);

        optimizeData({
            ext : ext,
            data: data
        }, function(error, data) {
            if (error)
                callback(error);
            else
                Util.exec.if(ext !== '.css', function(error, optimizedData) {
                    var isStr   = Util.isString(optimizedData);

                    if (isStr)
                        data    = optimizedData;

                    ++readFilesCount;

                    writeFile(minFileName, data, isLog, function(dataMin) {
                        if (returnName)
                            callback(null, minFileName);
                        else
                            callback(null, dataMin);
                        });
                    }, function(callback) {
                        var img = getModule('img');
                        img.optimize(filename, data, callback);
                    });
            });
    }

    /**
     * function get name of file in min folder
     *
     * @param name
     * @param ext
     */
    function getName(name, ext) {
        var ret, minFileName;

        if (Util.isString(name)) {
            if (!ext)
                ext         = path.extname(name);

            minFileName = crypto.createHash('sha1')
                .update(name)
                .digest('hex') + ext;

            ret = MinFolder + minFileName;
        }

        return ret;
    }

    /*
     * Функция записывает файла
     * и выводит ошибку или сообщает,
     * что файл успешно записан
     */
    function writeFile(name, data, isLog, callback) {
        fs.writeFile(name, data, function(error) {
            var basename = path.basename(name),
                msg = 'minify: file ' + basename + ' written...';

            log(error || msg, isLog);

            Util.exec(callback, data);
        });
    }

    function log(msg, isLog) {
        if (isLog)
            Util.log(msg);
    }

})();
<commit_msg>fix(minify) req.path -> req.url<commit_after>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
(function() {
    'use strict';

    var DIR         = __dirname + '/',
        os          = require('os'),
        crypto      = require('crypto'),
        fs          = require('fs'),
        path        = require('path'),

        mkdirp      = require('mkdirp'),
        ischanged   = require('ischanged'),
        Util        = require('util-io'),
        ponse       = require('ponse'),

        WIN         = process.platform === 'win32',

        MinFolder   = getDir() || DIR + 'min/';

    module.exports  = minify;

    function getModule(name) {
        return require(DIR + name);
    }

    function optimizeData(params, callback) {
        var module, p = params;

        switch(p.ext) {
            case '.js':
                module = getModule('js');
                module._uglifyJS(p.data, callback);
                break;

            case '.html':
                module = getModule('html');
                module.htmlMinify(p.data, callback);
                break;

            case '.css':
                module = getModule('css');
                module._cleanCSS(p.data, callback);
                break;
        }
    }

    function minify(name, options, callback) {
        var isChanged, isExist, ret,
            isObject    = Util.isObject(name),
            exec        = Util.exec,
            nameMin     = getName(name);

        if (!callback)
            callback = options;

        if (!options && !callback)
            ret = middle.bind(null, name);
        else if (isObject) {
            optimizeData(name, callback);
        } else {
            isChanged   = exec.with(ischanged, name),
            isExist     = exec.with(fs.lstat, nameMin);

            exec.parallel([isChanged, isExist], function(error, changed, exists) {
                if (changed || !exists)
                    optimize(name, options, callback);
                else
                    if (options.returnName)
                        callback(null, nameMin);
                    else
                        fs.readFile(nameMin, 'utf8', callback);
            });
        }

        return ret;
    }

    function getDir() {
        var dir;

        if (os.tmpdir) {
            dir     = os.tmpdir();
            dir     += '/minify';

            if (!WIN)
                dir += '/' + process.getuid();

            dir     += '/';
        }

        return dir;
    }

    function makeDir(callback) {
        var ANY_MASK    = 0,
            umask       = process.umask(ANY_MASK);

        mkdirp(MinFolder, function(error) {
            process.umask(umask);

            if (error && error.code === 'EEXIST')
                callback();
            else
                callback(error);
        });
    }

    function middle(options, req, res, next) {
        var isMinify, dir, is, isFunction,
            name        = req.url,
            isExt       = Util.checkExt(name, ['js', 'css', 'html']);

        Util.checkArgs([options], ['options']);

        is              = options.is;
        dir             = options.dir || './';

        isFunction      = Util.isFunction(is);
        name            = path.join(dir, name);

        if (isFunction)
            isMinify    = is();
        else
            isMinify    = is || Util.isUndefined(is);

        if (!isExt || !isMinify)
            next();
        else
            minify(name, {
                log         : options.log,
                returnName  : true
            }, function(error, name) {
                if (error)
                    next();
                else
                    ponse.sendFile({
                        request: req,
                        response: res,
                        name: name,
                        gzip: true,
                        cache:true,
                    });
            });
    }

    /**
     * function minificate js,css and html files
     *
     * @param files     -   js, css or html file path
     * @param options   -   object contain main options
     */
    function optimize(file, options, callback) {
        if (!callback)
            callback = options;

        Util.checkArgs(arguments, ['file', 'callback']);

        makeDir(function(error) {
            var name, basename, msg,
                islog   = options.log,
                isObj   = Util.isObject(file);

            if (error)
                log(error, islog);

            if (isObj)
                name    = Object.keys(file)[0];
            else
                name    = file;

            basename    = path.basename(name);
            msg         = 'minify: reading file ' + basename + '...';

            log(msg, islog);

            fs.readFile(name, 'utf8', function(error, data) {
                if (error)
                    callback(error);
                else
                    onDataRead(file, data, options, callback);
            });
        });
    }

   /**
    * Processing of files
    * @param fileData {name, data}
    */
    function onDataRead(filename, data, options, callback) {
        var ext, minFileName,
            readFilesCount  = 0,
            isLog           = options.log,
            returnName      = options.returnName,
            basename        = path.basename(filename);

        log('minify: file ' + basename + ' read', isLog);

        ext         = path.extname(filename);
        minFileName = getName(filename, ext);

        optimizeData({
            ext : ext,
            data: data
        }, function(error, data) {
            if (error)
                callback(error);
            else
                Util.exec.if(ext !== '.css', function(error, optimizedData) {
                    var isStr   = Util.isString(optimizedData);

                    if (isStr)
                        data    = optimizedData;

                    ++readFilesCount;

                    writeFile(minFileName, data, isLog, function(dataMin) {
                        if (returnName)
                            callback(null, minFileName);
                        else
                            callback(null, dataMin);
                        });
                    }, function(callback) {
                        var img = getModule('img');
                        img.optimize(filename, data, callback);
                    });
            });
    }

    /**
     * function get name of file in min folder
     *
     * @param name
     * @param ext
     */
    function getName(name, ext) {
        var ret, minFileName;

        if (Util.isString(name)) {
            if (!ext)
                ext         = path.extname(name);

            minFileName = crypto.createHash('sha1')
                .update(name)
                .digest('hex') + ext;

            ret = MinFolder + minFileName;
        }

        return ret;
    }

    /*
     * Функция записывает файла
     * и выводит ошибку или сообщает,
     * что файл успешно записан
     */
    function writeFile(name, data, isLog, callback) {
        fs.writeFile(name, data, function(error) {
            var basename = path.basename(name),
                msg = 'minify: file ' + basename + ' written...';

            log(error || msg, isLog);

            Util.exec(callback, data);
        });
    }

    function log(msg, isLog) {
        if (isLog)
            Util.log(msg);
    }

})();
<|endoftext|>


<commit_before>'use strict';

var Database    = require('dbjs')
  , DbjsEvent   = require('dbjs/_setup/event')
  , validDbjs   = require('dbjs/valid-dbjs')
  , isGetter    = require('dbjs/_setup/utils/is-getter')
  , customError = require('es5-ext/error/custom')

  , getPrototypeOf = Object.getPrototypeOf
  , migrateType, migrateObject, migrateProperty, migrateProperties;

migrateType = function (type, targetDatabase) {
	var targetType = targetDatabase.objects.getById(type.__id__);
	if (targetType) return targetType;
	targetType = migrateObject(type, targetDatabase);
	migrateProperties(type.prototype, targetDatabase);
	return targetType;
};

migrateObject = function (obj, targetDatabase) {
	var prototype, sourceEvent, targetObj;
	targetObj = targetDatabase.objects.getById(obj.__id__);
	if (targetObj) return targetObj;
	prototype = migrateObject(getPrototypeOf(obj), targetDatabase);
	if (typeof obj !== 'function') migrateType(obj.constructor, targetDatabase);
	if (obj.object !== obj) {
		if (typeof obj.object === 'function') migrateType(obj.constructor, targetDatabase);
		else migrateObject(obj.object, targetDatabase);
	}
	sourceEvent = obj._lastOwnEvent_;
	if (obj.master === obj) {
		new DbjsEvent(targetObj = targetDatabase.objects.unserialize(obj.__id__, prototype),
			prototype, (sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	}
	migrateProperties(obj, targetDatabase);
	return targetObj;
};

migrateProperty = function (sourceDesc, targetDatabase) {
	var hasInformation = false, value, sourceEvent;
	if (targetDatabase.objects.getById(sourceDesc.__id__)) return hasInformation;
	if (migrateProperty(getPrototypeOf(sourceDesc), targetDatabase)) hasInformation = true;
	sourceDesc._forEachOwnDescriptor_(function (subDesc) {
		var key = subDesc.key, sourceEvent, value;
		hasInformation = true;
		if (key === 'statsBase') return;
		if (key === 'type') migrateType(sourceDesc.type, targetDatabase);
		sourceEvent = subDesc._lastOwnEvent_;
		value = sourceDesc[key];
		if (value instanceof sourceDesc.database.Base) {
			value = targetDatabase.objects.getById(value.__id__);
			if (!value) {
				throw new TypeError("Could not migrate object of id: ", sourceDesc[key].__id__);
			}
		}
		new DbjsEvent(targetDatabase.objects.unserialize(subDesc.__id__), value,
			(sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	});
	if (!sourceDesc.hasOwnProperty('_value_') || (sourceDesc._value_ === undefined)) {
		return hasInformation;
	}
	value = sourceDesc._value_;
	if (sourceDesc.master instanceof sourceDesc.database.Object) {
		if (isGetter(value)) {
			if (!sourceDesc.hasOwnProperty('statsBase')) return hasInformation;
			value = sourceDesc.statsBase;
			if (value == null) return hasInformation;
		}
	}
	sourceEvent = sourceDesc._lastOwnEvent_;
	new DbjsEvent(targetDatabase.objects.unserialize(sourceDesc.__valueId__), value,
		(sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	return true;
};

migrateProperties = function (source, targetDatabase) {
	var isFullCopy = !(source.master instanceof source.database.Object), sKey, desc, anyDefined;

	for (sKey in source.__descriptors__) {
		desc = source.__descriptors__[sKey];
		if (desc.nested) {
			if (migrateProperties(source.get(desc.key), targetDatabase)) {
				anyDefined = true;
				migrateProperty(desc, targetDatabase);
			}
			if (!isFullCopy) continue;
		}
		if (desc.object !== source) continue;
		if (!isFullCopy && !desc.hasOwnProperty('statsBase')) continue;
		if (migrateProperty(desc, targetDatabase)) anyDefined = true;
	}
	return anyDefined;
};

module.exports = function (mainDb) {
	var statsDb;
	validDbjs(mainDb);
	if (!mainDb.User) throw customError('User type not found on source database', 'NO_USER_IN_DB');

	statsDb = new Database();

	migrateType(mainDb.User, statsDb);
	return statsDb;
};
<commit_msg>Fixed nested objects handling<commit_after>'use strict';

var Database    = require('dbjs')
  , DbjsEvent   = require('dbjs/_setup/event')
  , validDbjs   = require('dbjs/valid-dbjs')
  , isGetter    = require('dbjs/_setup/utils/is-getter')
  , customError = require('es5-ext/error/custom')

  , getPrototypeOf = Object.getPrototypeOf
  , migrateType, migrateObject, migrateProperty, migrateProperties;

migrateType = function (type, targetDatabase) {
	var targetType = targetDatabase.objects.getById(type.__id__);
	if (targetType) return targetType;
	targetType = migrateObject(type, targetDatabase);
	migrateProperties(type.prototype, targetDatabase);
	return targetType;
};

migrateObject = function (obj, targetDatabase) {
	var prototype, sourceEvent, targetObj;
	targetObj = targetDatabase.objects.getById(obj.__id__);
	if (targetObj) return targetObj;
	prototype = migrateObject(getPrototypeOf(obj), targetDatabase);
	if (typeof obj !== 'function') migrateType(obj.constructor, targetDatabase);
	if (obj.object !== obj) {
		if (typeof obj.object === 'function') migrateType(obj.object, targetDatabase);
		else migrateObject(obj.object, targetDatabase);
	}
	sourceEvent = obj._lastOwnEvent_;
	if (obj.master === obj) {
		new DbjsEvent(targetObj = targetDatabase.objects.unserialize(obj.__id__, prototype),
			prototype, (sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	}
	migrateProperties(obj, targetDatabase);
	return targetObj;
};

migrateProperty = function (sourceDesc, targetDatabase) {
	var hasInformation = false, value, sourceEvent;
	if (targetDatabase.objects.getById(sourceDesc.__id__)) return hasInformation;
	if (migrateProperty(getPrototypeOf(sourceDesc), targetDatabase)) hasInformation = true;
	sourceDesc._forEachOwnDescriptor_(function (subDesc) {
		var key = subDesc.key, sourceEvent, value;
		hasInformation = true;
		if (key === 'statsBase') return;
		if (key === 'type') migrateType(sourceDesc.type, targetDatabase);
		sourceEvent = subDesc._lastOwnEvent_;
		value = sourceDesc[key];
		if (value instanceof sourceDesc.database.Base) {
			value = targetDatabase.objects.getById(value.__id__);
			if (!value) {
				throw new TypeError("Could not migrate object of id: ", sourceDesc[key].__id__);
			}
		}
		new DbjsEvent(targetDatabase.objects.unserialize(subDesc.__id__), value,
			(sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	});
	if (!sourceDesc.hasOwnProperty('_value_') || (sourceDesc._value_ === undefined)) {
		return hasInformation;
	}
	value = sourceDesc._value_;
	if (sourceDesc.master instanceof sourceDesc.database.Object) {
		if (isGetter(value)) {
			if (!sourceDesc.hasOwnProperty('statsBase')) return hasInformation;
			value = sourceDesc.statsBase;
			if (value == null) return hasInformation;
		}
	}
	sourceEvent = sourceDesc._lastOwnEvent_;
	new DbjsEvent(targetDatabase.objects.unserialize(sourceDesc.__valueId__), value,
		(sourceEvent && sourceEvent.stamp) || 0); //jslint: ignore
	return true;
};

migrateProperties = function (source, targetDatabase) {
	var isFullCopy = !(source.master instanceof source.database.Object), sKey, desc, anyDefined;

	for (sKey in source.__descriptors__) {
		desc = source.__descriptors__[sKey];
		if (desc.nested) {
			if (migrateProperties(source.get(desc.key), targetDatabase)) {
				anyDefined = true;
				migrateProperty(desc, targetDatabase);
			}
			if (!isFullCopy) continue;
		}
		if (desc.object !== source) continue;
		if (!isFullCopy && !desc.hasOwnProperty('statsBase')) continue;
		if (migrateProperty(desc, targetDatabase)) anyDefined = true;
	}
	return anyDefined;
};

module.exports = function (mainDb) {
	var statsDb;
	validDbjs(mainDb);
	if (!mainDb.User) throw customError('User type not found on source database', 'NO_USER_IN_DB');

	statsDb = new Database();

	migrateType(mainDb.User, statsDb);
	return statsDb;
};
<|endoftext|>