<commit_before>(function($, $TD, TD){
  //
  // Variable: Current highlighted column jQuery object.
  //
  var highlightedColumnEle;

  //
  // Variable: Currently highlighted tweet jQuery object.
  //
  var highlightedTweetEle;

  //
  // Function: Initializes TweetD*ck events. Called after the website app is loaded.
  //
  var initializeTweetDck = function(){
    // Settings button hook
    $("[data-action='settings-menu']").click(function(){
      setTimeout(function(){
        var menu = $(".js-dropdown-content").children("ul").first();
        if (menu.length === 0)return;

        menu.children(".drp-h-divider").last().after([
          '
'+$TD.brandName+' settings
',
          '
'+$TD.brandName+' plugins
',
          '

'
        ].join(""));

        var buttons = menu.children("[data-std]");

        buttons.on("click", "a", function(){
          var action = $(this).attr("data-action");

          if (action === "td-settings"){
            $TD.openSettingsMenu();
          }
          else if (action === "td-plugins"){
            $TD.openPluginsMenu();
          }
        });

        buttons.hover(function(){
          $(this).addClass("is-selected");
        }, function(){
          $(this).removeClass("is-selected");
        });
      }, 0);
    });

    // Notification handling
    $.subscribe("/notifications/new", function(obj){
      for(let index = obj.items.length-1; index >= 0; index--){
        onNewTweet(obj.column, obj.items[index]);
      }
    });

    // Setup video element replacement and fix missing target in user links
    new MutationObserver(function(){
      $("video").each(function(){
        $(this).parent().replaceWith("► Open video in browser");
      });

      $("a[rel='user']").attr("target", "_blank");
    }).observe($(".js-app-columns")[0], {
      childList: true,
      subtree: true
    });

    // Finish init and load plugins
    $TD.loadFontSizeClass(TD.settings.getFontSize());
    $TD.loadNotificationHeadContents(getNotificationHeadContents());

    window.TD_APP_READY = true;

    if (window.TD_PLUGINS){
      window.TD_PLUGINS.onReady();
    }
  };

  //
  // Function: Prepends code at the beginning of a function. If the prepended function returns true, execution of the original function is cancelled.
  //
  var prependToFunction = function(func, extension){
    return function(){
      return extension.apply(this, arguments) === true ? undefined : func.apply(this, arguments);
    };
  };

  //
  // Function: Appends code at the end of a function.
  //
  var appendToFunction = function(func, extension){
    return function(){
      var res = func.apply(this, arguments);
      extension.apply(this, arguments);
      return res;
    };
  };

  //
  // Function: Event callback for a new tweet.
  //
  var onNewTweet = function(column, tweet){
    if (column.model.getHasNotification()){
      var html = $(tweet.render({
        withFooter: false,
        withTweetActions: false,
        withMediaPreview: true,
        isMediaPreviewOff: true,
        isMediaPreviewSmall: false,
        isMediaPreviewLarge: false
      }));

      html.css("border", "0");
      html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice

      var url = html.find("time").first().children("a").first().attr("href") || "";

      $TD.onTweetPopup(html.html(), url, tweet.text.length); // TODO column
    }
    else if (column.model.getHasSound()){
      $TD.onTweetSound(); // TODO disable original
    }
  };

  //
  // Function: Retrieves the tags to be put into  for notification HTML code.
  //
  var getNotificationHeadContents = function(){
    var tags = [];

    $(document.head).children("link[rel='stylesheet'],meta[charset],meta[http-equiv]").each(function(){
      tags.push($(this)[0].outerHTML);
    });

    return tags.join("");
  };

  //
  // Block: Observe the app
 element and initialize TweetD*ck whenever possible.
  //
  var app = $("body").children(".js-app");

  new MutationObserver(function(){
    if (window.TD_APP_READY && app.hasClass("is-hidden")){
      window.TD_APP_READY = false;
    }
    else if (!window.TD_APP_READY && !app.hasClass("is-hidden")){
      initializeTweetDck();
    }
  }).observe(app[0], {
    attributes: true,
    attributeFilter: [ "class" ]
  });

  //
  // Block: Hook into settings object to detect when the settings change.
  //
  TD.settings.setFontSize = appendToFunction(TD.settings.setFontSize, function(name){
    $TD.loadFontSizeClass(name);
  });

  TD.settings.setTheme = appendToFunction(TD.settings.setTheme, function(){
    setTimeout(function(){
      $TD.loadNotificationHeadContents(getNotificationHeadContents());
    }, 0);
  });

  //
  // Block: Force popup notification settings.
  //
  TD.controller.notifications.hasNotifications = function(){
    return true;
  };

  TD.controller.notifications.isPermissionGranted = function(){
    return true;
  };

  //
  // Block: Expand shortened links on hover or display tooltip.
  //
  (function(){
    var cutStart = function(str, search){
      return str.startsWith(search) ? str.substr(search.length) : str;
    };

    var prevMouseX = -1, prevMouseY = -1;
    var tooltipTimer, tooltipDisplayed;

    $(document.body).delegate("a[data-full-url]", "mouseenter mouseleave mousemove", function(e){
      var me = $(this);

      if (e.type === "mouseenter"){
        var text = me.text();

        if (text.charCodeAt(text.length-1) !== 8230){ // horizontal ellipsis
          return;
        }

        if ($TD.expandLinksOnHover){
          tooltipTimer = window.setTimeout(function(){
            var expanded = me.attr("data-full-url");
            expanded = cutStart(expanded, "https://");
            expanded = cutStart(expanded, "http://");
            expanded = cutStart(expanded, "www.");

            me.attr("td-prev-text", text);
            me.text(expanded);
          }, 200);
        }
        else{
          tooltipTimer = window.setTimeout(function(){
            $TD.displayTooltip(me.attr("data-full-url"), false);
            tooltipDisplayed = true;
          }, 400);
        }
      }
      else if (e.type === "mouseleave"){
        if ($TD.expandLinksOnHover){
          var prevText = me.attr("td-prev-text");

          if (prevText){
            me.text(prevText);
          }
        }

        window.clearTimeout(tooltipTimer);

        if (tooltipDisplayed){
          tooltipDisplayed = false;
          $TD.displayTooltip(null, false);
        }
      }
      else if (e.type === "mousemove"){
        if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
          $TD.displayTooltip(me.attr("data-full-url"), false);
          prevMouseX = e.clientX;
          prevMouseY = e.clientY;
        }
      }
    });
  })();

  //
  // Block: Allow bypassing of t.co in context menus.
  //
  $(document.body).delegate("a", "contextmenu", function(){
    $TD.setLastRightClickedLink($(this).attr("data-full-url") || "");
  });

  //
  // Block: Hook into the notification sound effect.
  //
  (function(){
    var soundEle = document.getElementById("update-sound");

    soundEle.play = prependToFunction(soundEle.play, function(){
      return $TD.muteNotifications;
    });
  })();

  /* TODO document.getElementById("update-sound").play = function(){
    $TD.onTweetSound();
  };*/

  //
  // Block: Update highlighted column.
  //
  app.delegate("section", "mouseenter mouseleave", function(e){
    if (e.type === "mouseenter"){
      highlightedColumnEle = $(this);
    }
    else if (e.type === "mouseleave"){
      highlightedColumnEle = null;
    }
  });

  //
  // Block: Copy tweet address and update highlighted tweet.
  //
  (function(){
    var lastTweet = "";

    var updateHighlightedTweet = function(link, embeddedLink){
      if (lastTweet !== link){
        $TD.setLastHighlightedTweet(link, embeddedLink);
        lastTweet = link;
      }
    };

    app.delegate("article.js-stream-item", "mouseenter mouseleave", function(e){
      if (e.type === "mouseenter"){
        highlightedTweetEle = $(this);

        var link = $(this).find("time").first().children("a").first();
        var embedded = $(this).find(".quoted-tweet[data-tweet-id]").first();

        updateHighlightedTweet(link.length > 0 ? link.attr("href") : "", embedded.length > 0 ? embedded.find(".account-link").first().attr("href")+"/status/"+embedded.attr("data-tweet-id") : "");
      }
      else if (e.type === "mouseleave"){
        highlightedTweetEle = null;
        updateHighlightedTweet("", "");
      }
    });
  })();

  //
  // Block: Screenshot tweet to clipboard.
  //
  (function(){
    var selectedTweet;

    app.delegate("article.js-stream-item", "contextmenu", function(){
      selectedTweet = $(this);
    });

    window.TDGF_triggerScreenshot = function(){
      if (selectedTweet){
        selectedTweet.find("footer").last().remove();
        $TD.screenshotTweet(selectedTweet.html(), selectedTweet.width(), selectedTweet.height());
      }
    };
  })();

  //
  // Block: Paste images when tweeting.
  //
  (function(){
    var lastPasteElement;
    var prevScrollTop;

    var getScroller = function(){
      return $(".js-drawer").find(".js-compose-scroller").first().children().first();
    };

    var clickUpload = function(){
      var button = $(".js-add-image-button").first();

      var scroller = getScroller();
      prevScrollTop = scroller.scrollTop();

      scroller.scrollTop(0);
      scroller.scrollTop(button.offset().top); // scrolls the button into view

      var buttonPos = button.children().first().offset(); // finds the camera icon offset
      $TD.clickUploadImage(Math.floor(buttonPos.left), Math.floor(buttonPos.top));
    };

    $(".js-app").delegate(".js-compose-text,.js-reply-tweetbox", "paste", function(){
      lastPasteElement = $(this);
      $TD.tryPasteImage();
    });

    window.TDGF_tryPasteImage = function(){
      if (lastPasteElement){
        var parent = lastPasteElement.parent();

        if (parent.siblings(".js-add-image-button").length === 0){
          var pop = parent.closest(".js-inline-reply,.rpl").find(".js-inline-compose-pop,.js-reply-popout");

          if (pop.length === 0){
            lastPasteElement = null;
            return;
          }

          pop.click();

          var drawer = $(".js-drawer");
          var counter = 0;

          var interval = setInterval(function(){
            if (drawer.offset().left >= 195){
              clickUpload();
              clearInterval(interval);
            }
            else if (++counter >= 10){
              clearInterval(interval);
            }
          }, 51);
        }
        else{
          clickUpload();
        }

        lastPasteElement = null;
      }
    };

    window.TDGF_tryPasteImageFinish = function(){
      setTimeout(function(){
        getScroller().scrollTop(prevScrollTop);
        $(".js-drawer").find(".js-compose-text").first()[0].focus();
      }, 10);
    };
  })();

  //
  // Block: Support for extra mouse buttons.
  //
  (function(){
    var tryClickSelector = function(selector, parent){
      return $(selector, parent).click().length;
    };

    var tryCloseModal = function(){
      var modal = $("#open-modal");
      return modal.is(":visible") && tryClickSelector("a[rel=dismiss]", modal);
    };

    var tryCloseHighlightedColumn = function(){
      if (highlightedColumnEle){
        var column = highlightedColumnEle.closest(".js-column");
        return (column.is(".is-shifted-2") && tryClickSelector(".js-tweet-social-proof-back", column)) || (column.is(".is-shifted-1") && tryClickSelector(".js-column-back", column));
      }
    };

    window.TDGF_onMouseClickExtra = function(button){
      if (button === 1){ // back button
        tryCloseModal() ||
        tryClickSelector(".js-inline-compose-close") ||
        tryCloseHighlightedColumn() ||
        tryClickSelector(".js-app-content.is-open .js-drawer-close:visible") ||
        tryClickSelector(".is-shifted-2 .js-tweet-social-proof-back") ||
        $(".js-column-back").click();
      }
      else if (button === 2){ // forward button
        if (highlightedTweetEle){
          highlightedTweetEle.children().first().click();
        }
      }
    };
  })();

  //
  // Block: Fix scheduled tweets not showing up sometimes.
  //
  $(document).on("dataTweetSent", function(e, data){
    if (data.response.state && data.response.state === "scheduled"){
      var column = Object.values(TD.controller.columnManager.getAll()).find(column => column.model.state.type === "scheduled");

      if (column){
        setTimeout(function(){
          column.reloadTweets();
        }, 1000);
      }
    }
  });

  //
  // Block: Inject custom CSS and layout into the page.
  //
  (function(){
    var styleOfficial = document.createElement("style");
    document.head.appendChild(styleOfficial);

    styleOfficial.sheet.insertRule("a[data-full-url] { word-break: break-all; }", 0); // break long urls
    styleOfficial.sheet.insertRule(".column-nav-link .attribution { position: absolute; }", 0); // fix cut off account names
    styleOfficial.sheet.insertRule(".txt-base-smallest .badge-verified:before { height: 13px !important; }", 0); // fix cut off badge icon
    styleOfficial.sheet.insertRule(".keyboard-shortcut-list { vertical-align: top; }", 0); // fix keyboard navigation alignment

    if ($TD.hasCustomBrowserCSS){
      var styleCustom = document.createElement("style");
      styleCustom.innerHTML = $TD.customBrowserCSS;
      document.head.appendChild(styleCustom);
    }
  })();
})($, $TD, TD);
<commit_msg>Fix screenshot script modifying original elements and missing html classes<commit_after>(function($, $TD, TD){
  //
  // Variable: Current highlighted column jQuery object.
  //
  var highlightedColumnEle;

  //
  // Variable: Currently highlighted tweet jQuery object.
  //
  var highlightedTweetEle;

  //
  // Function: Initializes TweetD*ck events. Called after the website app is loaded.
  //
  var initializeTweetDck = function(){
    // Settings button hook
    $("[data-action='settings-menu']").click(function(){
      setTimeout(function(){
        var menu = $(".js-dropdown-content").children("ul").first();
        if (menu.length === 0)return;

        menu.children(".drp-h-divider").last().after([
          '
'+$TD.brandName+' settings
',
          '
'+$TD.brandName+' plugins
',
          '

'
        ].join(""));

        var buttons = menu.children("[data-std]");

        buttons.on("click", "a", function(){
          var action = $(this).attr("data-action");

          if (action === "td-settings"){
            $TD.openSettingsMenu();
          }
          else if (action === "td-plugins"){
            $TD.openPluginsMenu();
          }
        });

        buttons.hover(function(){
          $(this).addClass("is-selected");
        }, function(){
          $(this).removeClass("is-selected");
        });
      }, 0);
    });

    // Notification handling
    $.subscribe("/notifications/new", function(obj){
      for(let index = obj.items.length-1; index >= 0; index--){
        onNewTweet(obj.column, obj.items[index]);
      }
    });

    // Setup video element replacement and fix missing target in user links
    new MutationObserver(function(){
      $("video").each(function(){
        $(this).parent().replaceWith("► Open video in browser");
      });

      $("a[rel='user']").attr("target", "_blank");
    }).observe($(".js-app-columns")[0], {
      childList: true,
      subtree: true
    });

    // Finish init and load plugins
    $TD.loadFontSizeClass(TD.settings.getFontSize());
    $TD.loadNotificationHeadContents(getNotificationHeadContents());

    window.TD_APP_READY = true;

    if (window.TD_PLUGINS){
      window.TD_PLUGINS.onReady();
    }
  };

  //
  // Function: Prepends code at the beginning of a function. If the prepended function returns true, execution of the original function is cancelled.
  //
  var prependToFunction = function(func, extension){
    return function(){
      return extension.apply(this, arguments) === true ? undefined : func.apply(this, arguments);
    };
  };

  //
  // Function: Appends code at the end of a function.
  //
  var appendToFunction = function(func, extension){
    return function(){
      var res = func.apply(this, arguments);
      extension.apply(this, arguments);
      return res;
    };
  };

  //
  // Function: Event callback for a new tweet.
  //
  var onNewTweet = function(column, tweet){
    if (column.model.getHasNotification()){
      var html = $(tweet.render({
        withFooter: false,
        withTweetActions: false,
        withMediaPreview: true,
        isMediaPreviewOff: true,
        isMediaPreviewSmall: false,
        isMediaPreviewLarge: false
      }));

      html.css("border", "0");
      html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice

      var url = html.find("time").first().children("a").first().attr("href") || "";

      $TD.onTweetPopup(html.html(), url, tweet.text.length); // TODO column
    }
    else if (column.model.getHasSound()){
      $TD.onTweetSound(); // TODO disable original
    }
  };

  //
  // Function: Retrieves the tags to be put into  for notification HTML code.
  //
  var getNotificationHeadContents = function(){
    var tags = [];

    $(document.head).children("link[rel='stylesheet'],meta[charset],meta[http-equiv]").each(function(){
      tags.push($(this)[0].outerHTML);
    });

    return tags.join("");
  };

  //
  // Block: Observe the app
 element and initialize TweetD*ck whenever possible.
  //
  var app = $("body").children(".js-app");

  new MutationObserver(function(){
    if (window.TD_APP_READY && app.hasClass("is-hidden")){
      window.TD_APP_READY = false;
    }
    else if (!window.TD_APP_READY && !app.hasClass("is-hidden")){
      initializeTweetDck();
    }
  }).observe(app[0], {
    attributes: true,
    attributeFilter: [ "class" ]
  });

  //
  // Block: Hook into settings object to detect when the settings change.
  //
  TD.settings.setFontSize = appendToFunction(TD.settings.setFontSize, function(name){
    $TD.loadFontSizeClass(name);
  });

  TD.settings.setTheme = appendToFunction(TD.settings.setTheme, function(){
    setTimeout(function(){
      $TD.loadNotificationHeadContents(getNotificationHeadContents());
    }, 0);
  });

  //
  // Block: Force popup notification settings.
  //
  TD.controller.notifications.hasNotifications = function(){
    return true;
  };

  TD.controller.notifications.isPermissionGranted = function(){
    return true;
  };

  //
  // Block: Expand shortened links on hover or display tooltip.
  //
  (function(){
    var cutStart = function(str, search){
      return str.startsWith(search) ? str.substr(search.length) : str;
    };

    var prevMouseX = -1, prevMouseY = -1;
    var tooltipTimer, tooltipDisplayed;

    $(document.body).delegate("a[data-full-url]", "mouseenter mouseleave mousemove", function(e){
      var me = $(this);

      if (e.type === "mouseenter"){
        var text = me.text();

        if (text.charCodeAt(text.length-1) !== 8230){ // horizontal ellipsis
          return;
        }

        if ($TD.expandLinksOnHover){
          tooltipTimer = window.setTimeout(function(){
            var expanded = me.attr("data-full-url");
            expanded = cutStart(expanded, "https://");
            expanded = cutStart(expanded, "http://");
            expanded = cutStart(expanded, "www.");

            me.attr("td-prev-text", text);
            me.text(expanded);
          }, 200);
        }
        else{
          tooltipTimer = window.setTimeout(function(){
            $TD.displayTooltip(me.attr("data-full-url"), false);
            tooltipDisplayed = true;
          }, 400);
        }
      }
      else if (e.type === "mouseleave"){
        if ($TD.expandLinksOnHover){
          var prevText = me.attr("td-prev-text");

          if (prevText){
            me.text(prevText);
          }
        }

        window.clearTimeout(tooltipTimer);

        if (tooltipDisplayed){
          tooltipDisplayed = false;
          $TD.displayTooltip(null, false);
        }
      }
      else if (e.type === "mousemove"){
        if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
          $TD.displayTooltip(me.attr("data-full-url"), false);
          prevMouseX = e.clientX;
          prevMouseY = e.clientY;
        }
      }
    });
  })();

  //
  // Block: Allow bypassing of t.co in context menus.
  //
  $(document.body).delegate("a", "contextmenu", function(){
    $TD.setLastRightClickedLink($(this).attr("data-full-url") || "");
  });

  //
  // Block: Hook into the notification sound effect.
  //
  (function(){
    var soundEle = document.getElementById("update-sound");

    soundEle.play = prependToFunction(soundEle.play, function(){
      return $TD.muteNotifications;
    });
  })();

  /* TODO document.getElementById("update-sound").play = function(){
    $TD.onTweetSound();
  };*/

  //
  // Block: Update highlighted column.
  //
  app.delegate("section", "mouseenter mouseleave", function(e){
    if (e.type === "mouseenter"){
      highlightedColumnEle = $(this);
    }
    else if (e.type === "mouseleave"){
      highlightedColumnEle = null;
    }
  });

  //
  // Block: Copy tweet address and update highlighted tweet.
  //
  (function(){
    var lastTweet = "";

    var updateHighlightedTweet = function(link, embeddedLink){
      if (lastTweet !== link){
        $TD.setLastHighlightedTweet(link, embeddedLink);
        lastTweet = link;
      }
    };

    app.delegate("article.js-stream-item", "mouseenter mouseleave", function(e){
      if (e.type === "mouseenter"){
        highlightedTweetEle = $(this);

        var link = $(this).find("time").first().children("a").first();
        var embedded = $(this).find(".quoted-tweet[data-tweet-id]").first();

        updateHighlightedTweet(link.length > 0 ? link.attr("href") : "", embedded.length > 0 ? embedded.find(".account-link").first().attr("href")+"/status/"+embedded.attr("data-tweet-id") : "");
      }
      else if (e.type === "mouseleave"){
        highlightedTweetEle = null;
        updateHighlightedTweet("", "");
      }
    });
  })();

  //
  // Block: Screenshot tweet to clipboard.
  //
  (function(){
    var selectedTweet;

    app.delegate("article.js-stream-item", "contextmenu", function(){
      selectedTweet = $(this);
    });

    window.TDGF_triggerScreenshot = function(){
      if (selectedTweet){
        var realWidth = selectedTweet.width();
        var realHeight = selectedTweet.height()-selectedTweet.find("footer").last().height();

        selectedTweet = selectedTweet.clone();
        selectedTweet.children().first().addClass($(document.documentElement).attr("class"));
        selectedTweet.find("footer").last().remove();

        $TD.screenshotTweet(selectedTweet.html(), realWidth, realHeight);
      }
    };
  })();

  //
  // Block: Paste images when tweeting.
  //
  (function(){
    var lastPasteElement;
    var prevScrollTop;

    var getScroller = function(){
      return $(".js-drawer").find(".js-compose-scroller").first().children().first();
    };

    var clickUpload = function(){
      var button = $(".js-add-image-button").first();

      var scroller = getScroller();
      prevScrollTop = scroller.scrollTop();

      scroller.scrollTop(0);
      scroller.scrollTop(button.offset().top); // scrolls the button into view

      var buttonPos = button.children().first().offset(); // finds the camera icon offset
      $TD.clickUploadImage(Math.floor(buttonPos.left), Math.floor(buttonPos.top));
    };

    $(".js-app").delegate(".js-compose-text,.js-reply-tweetbox", "paste", function(){
      lastPasteElement = $(this);
      $TD.tryPasteImage();
    });

    window.TDGF_tryPasteImage = function(){
      if (lastPasteElement){
        var parent = lastPasteElement.parent();

        if (parent.siblings(".js-add-image-button").length === 0){
          var pop = parent.closest(".js-inline-reply,.rpl").find(".js-inline-compose-pop,.js-reply-popout");

          if (pop.length === 0){
            lastPasteElement = null;
            return;
          }

          pop.click();

          var drawer = $(".js-drawer");
          var counter = 0;

          var interval = setInterval(function(){
            if (drawer.offset().left >= 195){
              clickUpload();
              clearInterval(interval);
            }
            else if (++counter >= 10){
              clearInterval(interval);
            }
          }, 51);
        }
        else{
          clickUpload();
        }

        lastPasteElement = null;
      }
    };

    window.TDGF_tryPasteImageFinish = function(){
      setTimeout(function(){
        getScroller().scrollTop(prevScrollTop);
        $(".js-drawer").find(".js-compose-text").first()[0].focus();
      }, 10);
    };
  })();

  //
  // Block: Support for extra mouse buttons.
  //
  (function(){
    var tryClickSelector = function(selector, parent){
      return $(selector, parent).click().length;
    };

    var tryCloseModal = function(){
      var modal = $("#open-modal");
      return modal.is(":visible") && tryClickSelector("a[rel=dismiss]", modal);
    };

    var tryCloseHighlightedColumn = function(){
      if (highlightedColumnEle){
        var column = highlightedColumnEle.closest(".js-column");
        return (column.is(".is-shifted-2") && tryClickSelector(".js-tweet-social-proof-back", column)) || (column.is(".is-shifted-1") && tryClickSelector(".js-column-back", column));
      }
    };

    window.TDGF_onMouseClickExtra = function(button){
      if (button === 1){ // back button
        tryCloseModal() ||
        tryClickSelector(".js-inline-compose-close") ||
        tryCloseHighlightedColumn() ||
        tryClickSelector(".js-app-content.is-open .js-drawer-close:visible") ||
        tryClickSelector(".is-shifted-2 .js-tweet-social-proof-back") ||
        $(".js-column-back").click();
      }
      else if (button === 2){ // forward button
        if (highlightedTweetEle){
          highlightedTweetEle.children().first().click();
        }
      }
    };
  })();

  //
  // Block: Fix scheduled tweets not showing up sometimes.
  //
  $(document).on("dataTweetSent", function(e, data){
    if (data.response.state && data.response.state === "scheduled"){
      var column = Object.values(TD.controller.columnManager.getAll()).find(column => column.model.state.type === "scheduled");

      if (column){
        setTimeout(function(){
          column.reloadTweets();
        }, 1000);
      }
    }
  });

  //
  // Block: Inject custom CSS and layout into the page.
  //
  (function(){
    var styleOfficial = document.createElement("style");
    document.head.appendChild(styleOfficial);

    styleOfficial.sheet.insertRule("a[data-full-url] { word-break: break-all; }", 0); // break long urls
    styleOfficial.sheet.insertRule(".column-nav-link .attribution { position: absolute; }", 0); // fix cut off account names
    styleOfficial.sheet.insertRule(".txt-base-smallest .badge-verified:before { height: 13px !important; }", 0); // fix cut off badge icon
    styleOfficial.sheet.insertRule(".keyboard-shortcut-list { vertical-align: top; }", 0); // fix keyboard navigation alignment

    if ($TD.hasCustomBrowserCSS){
      var styleCustom = document.createElement("style");
      styleCustom.innerHTML = $TD.customBrowserCSS;
      document.head.appendChild(styleCustom);
    }
  })();
})($, $TD, TD);
<|endoftext|>


<commit_before>Views.remote = function(win) {

	var channel_favorites = Titanium.UI.createButton({
		backgroundImage:'images/channel_view/channel_fav.png',
		backgroundSelectedImage:'images/channel_view/channel_fav_down.png',
		height:"40dp",
		width:"40dp",
		top:"1dp",
		right:"40dp"
	});

	channel_favorites.addEventListener('touchstart', compose(Layouts.application.openFavs, Feedback.buttonPress));

	var current_playing_view = Titanium.UI.createView({
		backgroundImage:'images/nowplaying/remote_now_showing_pane.png',
		visible: false,
		top: "235dp",
		height: "66dp",
		width: "270dp",
	});

	var playing_image = Titanium.UI.createView({
		width: "35dp",
		height: "35dp",
		left:"10dp",
		top:"5dp"
	})

	// It will post the text of this label to facebook.  Leave blank for it to work right.
	var playing_label = Titanium.UI.createLabel({
		text: "",
		width: "175dp",
		height: "25dp",
		top:"8dp",
		left:"52dp",
		color:"#FFFFFF",
		font:{fontFamily:'Helvetica Neue',fontSize:"18dp"},
	});

	var like_button = Titanium.UI.createButton({
		backgroundImage:"images/nowplaying/remote_fblike.png",
		backgroundSelectedImage:'images/nowplaying/remote_fblike_down.png',
		height:"35dp",
		width:"35dp",
		top:"5dp",
		right:"15dp"
	});

	like_button.addEventListener('touchstart', Controllers.remote.postToWall.partial(playing_label, playing_image));

	current_playing_view.add(playing_image);
	current_playing_view.add(playing_label);
	current_playing_view.add(like_button);

	var top_like_button = Titanium.UI.createButton({
		backgroundImage:"images/nowplaying/remote_fblike_gray.png",
		backgroundSelectedImage:'images/nowplaying/remote_fblike_down_gray.png',
		height:"40dp",
		width:"40dp",
		top:"-2dp",
		right:"77dp"
	});

	top_like_button.addEventListener('touchstart', Controllers.remote.postToWall.partial(playing_label, playing_image));

	var home_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_home.png',
		backgroundSelectedImage:'images/remote_view/remote_home_down.png',
		height:"40dp",
		width:"40dp",
		top:"1dp",
		right:"5dp"
	});

	home_button.addEventListener('touchstart', compose(Controllers.remote.displayPlaying.curry(playing_label, playing_image, current_playing_view, null), Controllers.remote.button("menu")));

	var return_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_backbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_backbtn_down.png',
		height:"35dp",
		width:"65dp",
		top:"195dp",
		left:"10dp"
	});

	return_button.addEventListener('touchstart', Controllers.remote.button("back"));

	var keyboard_field = Helpers.ui.keyboard();

	var keyboard_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_keyboardbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_keyboardbtn_down.png',
		height:"35dp",
		width:"65dp",
		top:"195dp",
		right:"10dp"
	});

	keyboard_button.addEventListener('touchstart', function(){
		Feedback.buttonPress();
		keyboard_field.focus();
	});

	if(Helpers.Application.isAndroid()) {
		keyboard_field.addEventListener('return', function() {
			keyboard_field2.focus();
		});
	};

	var keyboard_field2 = Titanium.UI.createTextField({
	  width:0,
	  height:0,
		top:0,
		autocorrect:false,
	  keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
	  returnKeyType:Titanium.UI.RETURNKEY_DONE
	});

	var arrow_controls = Titanium.UI.createView({
		backgroundImage:'images/remote_view/remote_mainbtns.png',
		top:"35dp",
		width:"188dp",
		height:"188dp"
	});

	var up_clickable = Titanium.UI.createView({
		top:"-15dp",
		width:"130dp",
		height:"70dp"
	});

	var down_clickable = Titanium.UI.createView({
		bottom:"-15dp",
		width:"130dp",
		height:"70dp"
	});

	var left_clickable = Titanium.UI.createView({
		left:"-10dp",
		height:"80dp",
		width:"78dp"
	});

	var right_clickable = Titanium.UI.createView({
		right:"-10dp",
		height:"80dp",
		width:"78dp"
	});

	var up_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_upbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_upbtn_down.png',
		height:"17dp",
		width:"30dp",
		top:"35dp"
	});

	up_clickable.addEventListener('touchstart', Controllers.remote.button("up"));

	var down_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_downbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_downbtn_down.png',
		height:"17dp",
		width:"30dp",
		bottom:"37dp"
	});

	down_clickable.addEventListener('touchstart', Controllers.remote.button("down"));

	var left_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_leftbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_leftbtn_down.png',
		height:"30dp",
		width:"17dp",
		left:"30dp"
	});

	left_clickable.addEventListener('touchstart', Controllers.remote.button("left"));

	var right_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_rightbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_rightbtn_down.png',
		height:"30dp",
		width:"17dp",
		right:"32dp"
	});

	right_clickable.addEventListener('touchstart', Controllers.remote.button("right"));

	var ok_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_okbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_okbtn_down.png',
		height:"62dp",
		width:"62dp"
	});

	ok_button.addEventListener('touchstart', compose(showNowPlaying, Controllers.remote.button("select")));

	var color_buttons = Titanium.UI.createView({
		bottom:"0dp",
		height:"60dp"
	});

	var red_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_redbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_redbtn_down.png',
		height:"38dp",
		width:"38dp",
		left:"33dp",
		bottom:"14dp"
	});

	var blue_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_bluebtn.png',
		backgroundSelectedImage:'images/remote_view/remote_bluebtn_down.png',
		height:"38dp",
		width:"38dp",
		right:"33dp",
		bottom:"14dp"
	});

	var green_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_greenbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_greenbtn_down.png',
		height:"38dp",
		width:"38dp",
		left:"105dp",
		bottom:"2dp"
	});

	var yellow_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_yellowbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_yellowbtn_down.png',
		height:"38dp",
		width:"38dp",
		right:"105dp",
		bottom:"2dp"
	});

	Views.play_controls(win);
	Helpers.ui.connecting(win);

	win.add(top_like_button);
	win.add(channel_favorites);
	win.add(home_button);
	win.add(return_button);
	win.add(keyboard_field2);
	win.add(keyboard_field);

	win.add(keyboard_button);

	up_clickable.add(up_button);
	down_clickable.add(down_button);
	left_clickable.add(left_button);
	right_clickable.add(right_button);

	arrow_controls.add(ok_button);
	arrow_controls.add(up_clickable);
	arrow_controls.add(down_clickable);
	arrow_controls.add(left_clickable);
	arrow_controls.add(right_clickable);

	win.add(arrow_controls);

	color_buttons.add(blue_button);
	color_buttons.add(red_button);
	color_buttons.add(green_button);
	color_buttons.add(yellow_button);
	win.add(color_buttons);
	win.add(current_playing_view);

	map(addFeedback, color_buttons.children);

	Ti.App.addEventListener('showPlaying', showNowPlaying);

	function showNowPlaying() {
		Xbmc.currentPlaying(Controllers.remote.displayPlaying.curry(playing_label, playing_image, current_playing_view));
	}

	function addFeedback(b) {
		b.addEventListener('click', Feedback.buttonPress);
	}
};
<commit_msg>quick update<commit_after>Views.remote = function(win) {

	var channel_favorites = Titanium.UI.createButton({
		backgroundImage:'images/channel_view/channel_fav.png',
		backgroundSelectedImage:'images/channel_view/channel_fav_down.png',
		height:"40dp",
		width:"40dp",
		top:"1dp",
		right:"40dp"
	});

	channel_favorites.addEventListener('touchstart', compose(Layouts.application.openFavs, Feedback.buttonPress));

	var current_playing_view = Titanium.UI.createView({
		backgroundImage:'images/nowplaying/remote_now_showing_pane.png',
		visible: false,
		top: "240dp",
		height: "66dp",
		width: "270dp",
	});

	var playing_image = Titanium.UI.createView({
		width: "35dp",
		height: "35dp",
		left:"10dp",
		top:"5dp"
	})

	// It will post the text of this label to facebook.  Leave blank for it to work right.
	var playing_label = Titanium.UI.createLabel({
		text: "",
		width: "175dp",
		height: "25dp",
		top:"8dp",
		left:"52dp",
		color:"#FFFFFF",
		font:{fontFamily:'Helvetica Neue',fontSize:"18dp"},
	});

	var like_button = Titanium.UI.createButton({
		backgroundImage:"images/nowplaying/remote_fblike.png",
		backgroundSelectedImage:'images/nowplaying/remote_fblike_down.png',
		height:"35dp",
		width:"35dp",
		top:"5dp",
		right:"15dp"
	});

	like_button.addEventListener('touchstart', Controllers.remote.postToWall.partial(playing_label, playing_image));

	current_playing_view.add(playing_image);
	current_playing_view.add(playing_label);
	current_playing_view.add(like_button);

	var top_like_button = Titanium.UI.createButton({
		backgroundImage:"images/nowplaying/remote_fblike_gray.png",
		backgroundSelectedImage:'images/nowplaying/remote_fblike_down_gray.png',
		height:"40dp",
		width:"40dp",
		top:"-2dp",
		right:"77dp"
	});

	top_like_button.addEventListener('touchstart', Controllers.remote.postToWall.partial(playing_label, playing_image));

	var home_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_home.png',
		backgroundSelectedImage:'images/remote_view/remote_home_down.png',
		height:"40dp",
		width:"40dp",
		top:"1dp",
		right:"5dp"
	});

	home_button.addEventListener('touchstart', compose(Controllers.remote.displayPlaying.curry(playing_label, playing_image, current_playing_view, null), Controllers.remote.button("menu")));

	var return_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_backbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_backbtn_down.png',
		height:"35dp",
		width:"65dp",
		top:"195dp",
		left:"10dp"
	});

	return_button.addEventListener('touchstart', Controllers.remote.button("back"));

	var keyboard_field = Helpers.ui.keyboard();

	var keyboard_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_keyboardbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_keyboardbtn_down.png',
		height:"35dp",
		width:"65dp",
		top:"195dp",
		right:"10dp"
	});

	keyboard_button.addEventListener('touchstart', function(){
		Feedback.buttonPress();
		keyboard_field.focus();
	});

	if(Helpers.Application.isAndroid()) {
		keyboard_field.addEventListener('return', function() {
			keyboard_field2.focus();
		});
	};

	var keyboard_field2 = Titanium.UI.createTextField({
	  width:0,
	  height:0,
		top:0,
		autocorrect:false,
	  keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
	  returnKeyType:Titanium.UI.RETURNKEY_DONE
	});

	var arrow_controls = Titanium.UI.createView({
		backgroundImage:'images/remote_view/remote_mainbtns.png',
		top:"35dp",
		width:"188dp",
		height:"188dp"
	});

	var up_clickable = Titanium.UI.createView({
		top:"-15dp",
		width:"130dp",
		height:"70dp"
	});

	var down_clickable = Titanium.UI.createView({
		bottom:"-15dp",
		width:"130dp",
		height:"70dp"
	});

	var left_clickable = Titanium.UI.createView({
		left:"-10dp",
		height:"80dp",
		width:"78dp"
	});

	var right_clickable = Titanium.UI.createView({
		right:"-10dp",
		height:"80dp",
		width:"78dp"
	});

	var up_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_upbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_upbtn_down.png',
		height:"17dp",
		width:"30dp",
		top:"35dp"
	});

	up_clickable.addEventListener('touchstart', Controllers.remote.button("up"));

	var down_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_downbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_downbtn_down.png',
		height:"17dp",
		width:"30dp",
		bottom:"37dp"
	});

	down_clickable.addEventListener('touchstart', Controllers.remote.button("down"));

	var left_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_leftbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_leftbtn_down.png',
		height:"30dp",
		width:"17dp",
		left:"30dp"
	});

	left_clickable.addEventListener('touchstart', Controllers.remote.button("left"));

	var right_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_rightbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_rightbtn_down.png',
		height:"30dp",
		width:"17dp",
		right:"32dp"
	});

	right_clickable.addEventListener('touchstart', Controllers.remote.button("right"));

	var ok_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_okbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_okbtn_down.png',
		height:"62dp",
		width:"62dp"
	});

	ok_button.addEventListener('touchstart', compose(showNowPlaying, Controllers.remote.button("select")));

	var color_buttons = Titanium.UI.createView({
		bottom:"0dp",
		height:"60dp"
	});

	var red_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_redbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_redbtn_down.png',
		height:"38dp",
		width:"38dp",
		left:"33dp",
		bottom:"14dp"
	});

	var blue_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_bluebtn.png',
		backgroundSelectedImage:'images/remote_view/remote_bluebtn_down.png',
		height:"38dp",
		width:"38dp",
		right:"33dp",
		bottom:"14dp"
	});

	var green_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_greenbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_greenbtn_down.png',
		height:"38dp",
		width:"38dp",
		left:"105dp",
		bottom:"2dp"
	});

	var yellow_button = Titanium.UI.createButton({
		backgroundImage:'images/remote_view/remote_yellowbtn.png',
		backgroundSelectedImage:'images/remote_view/remote_yellowbtn_down.png',
		height:"38dp",
		width:"38dp",
		right:"105dp",
		bottom:"2dp"
	});

	Views.play_controls(win);
	Helpers.ui.connecting(win);

	win.add(top_like_button);
	win.add(channel_favorites);
	win.add(home_button);
	win.add(return_button);
	win.add(keyboard_field2);
	win.add(keyboard_field);

	win.add(keyboard_button);

	up_clickable.add(up_button);
	down_clickable.add(down_button);
	left_clickable.add(left_button);
	right_clickable.add(right_button);

	arrow_controls.add(ok_button);
	arrow_controls.add(up_clickable);
	arrow_controls.add(down_clickable);
	arrow_controls.add(left_clickable);
	arrow_controls.add(right_clickable);

	win.add(arrow_controls);

	color_buttons.add(blue_button);
	color_buttons.add(red_button);
	color_buttons.add(green_button);
	color_buttons.add(yellow_button);
	win.add(color_buttons);
	win.add(current_playing_view);

	map(addFeedback, color_buttons.children);

	Ti.App.addEventListener('showPlaying', showNowPlaying);

	function showNowPlaying() {
		Xbmc.currentPlaying(Controllers.remote.displayPlaying.curry(playing_label, playing_image, current_playing_view));
	}

	function addFeedback(b) {
		b.addEventListener('click', Feedback.buttonPress);
	}
};
<|endoftext|>


<commit_before>
angular.module('openspecimen')
  .directive('osStoragePosition', function($modal, $timeout, Container) {
    function loadContainers(name, scope) {
      scope.entityType = scope.entity.getType();
      var params = {
        name: name,
        onlyFreeContainers: true
      }

      if (scope.entityType == 'specimen') {
        if (!scope.entity.type) {
          return;
        }

        angular.extend(params, {
          cpId: scope.cpId,
          specimenClass: scope.entity.specimenClass,
          specimenType: scope.entity.type,
          storeSpecimensEnabled: true,
          maxRecords: 10
        });
      } else {
        if (!scope.entity.siteName) {
          return;
        }

        angular.extend(params, {site: scope.entity.siteName});
      }

      var q = scope.containerListCache[JSON.stringify(params)];
      if (!q) {
        q = Container.query(params);
        scope.containerListCache[JSON.stringify(params)] = q;
      }

      return q.then(
        function(containers) {
          scope.containers = containers.map(
            function(container) {
              return container.name;
            }
          );
        }
      );
    };

    function watchOccupyingEntityChanges(scope) {
      var objType = scope.entity.getType() == 'specimen' ? 'entity.type' : 'entity.siteName';
      scope.$watch(objType, function(newVal, oldVal) {
        if (!newVal || newVal == oldVal) {
          return;
        }

        loadContainers('', scope);
      });
    }

    function linker(scope, element, attrs) {
      var entity = scope.entity;
      scope.containerListCache = scope.containerListCache || {};

      scope.onContainerChange = function() {
        entity.storageLocation = {name: entity.storageLocation.name};
      };

      scope.openPositionSelector = function() {
        var modalInstance = $modal.open({
          templateUrl: 'modules/common/storage-position-selector.html',
          controller: 'StoragePositionSelectorCtrl',
          size: 'lg',
          resolve: {
            entity: function() {
              return scope.entity
            },

            cpId: function() {
              return scope.cpId;
            }
          }
        });

        modalInstance.result.then(
          function(position) {
            scope.entity.storageLocation = scope.entity.storageLocation || {};
            angular.extend(scope.entity.storageLocation, position);
            $timeout(function() {
              angular.extend(scope.entity.storageLocation, position);
            });
          }
        );
      };

      scope.searchContainer = function(name) {
        loadContainers(name, scope);
      };

      watchOccupyingEntityChanges(scope);
    };

    return {
      restrict: 'E',

      replace: true,

      priority: 100,

      terminal: true,

      scope: {
        entity: '=',
        cpId: '=',
        containerListCache: '=?'
      },

      compile: function(tElem, tAttrs) {
        var select = tElem.find('os-select');
        var input = tElem.find('input');

        if (tAttrs.hasOwnProperty('osMdInput')) {
          var button = tElem.find('button');

          select.attr('os-md-input', '');
          input.attr('os-md-input', '');

          if (tAttrs.hasOwnProperty('editWhen')) {
            select.attr('edit-when', tAttrs.editWhen);
            input.attr('edit-when', tAttrs.editWhen);
            button.attr('ng-if', tAttrs.editWhen);
          }

          tElem.find('button')
            .addClass('btn-xs')         // make button smaller in size
            .css('margin-top', '15px'); // ensure button is aligned with other text fields;
                                        // 15 px is used to display labels for os-md-input fields
        }

        if (tAttrs.hasOwnProperty('hidePlaceholder')) {
          select.removeAttr('placeholder');
          input.removeAttr('placeholder');
        }

        return linker;
      },

      templateUrl: 'modules/common/storage-position.html'
    }
  });

<commit_msg>OPSMN-2437: Fixed vertical alignment of select storage position button on bulk specimen collection<commit_after>
angular.module('openspecimen')
  .directive('osStoragePosition', function($modal, $timeout, Container) {
    function loadContainers(name, scope) {
      scope.entityType = scope.entity.getType();
      var params = {
        name: name,
        onlyFreeContainers: true
      }

      if (scope.entityType == 'specimen') {
        if (!scope.entity.type) {
          return;
        }

        angular.extend(params, {
          cpId: scope.cpId,
          specimenClass: scope.entity.specimenClass,
          specimenType: scope.entity.type,
          storeSpecimensEnabled: true,
          maxRecords: 10
        });
      } else {
        if (!scope.entity.siteName) {
          return;
        }

        angular.extend(params, {site: scope.entity.siteName});
      }

      var q = scope.containerListCache[JSON.stringify(params)];
      if (!q) {
        q = Container.query(params);
        scope.containerListCache[JSON.stringify(params)] = q;
      }

      return q.then(
        function(containers) {
          scope.containers = containers.map(
            function(container) {
              return container.name;
            }
          );
        }
      );
    };

    function watchOccupyingEntityChanges(scope) {
      var objType = scope.entity.getType() == 'specimen' ? 'entity.type' : 'entity.siteName';
      scope.$watch(objType, function(newVal, oldVal) {
        if (!newVal || newVal == oldVal) {
          return;
        }

        loadContainers('', scope);
      });
    }

    function linker(scope, element, attrs) {
      var entity = scope.entity;
      scope.containerListCache = scope.containerListCache || {};

      scope.onContainerChange = function() {
        entity.storageLocation = {name: entity.storageLocation.name};
      };

      scope.openPositionSelector = function() {
        var modalInstance = $modal.open({
          templateUrl: 'modules/common/storage-position-selector.html',
          controller: 'StoragePositionSelectorCtrl',
          size: 'lg',
          resolve: {
            entity: function() {
              return scope.entity
            },

            cpId: function() {
              return scope.cpId;
            }
          }
        });

        modalInstance.result.then(
          function(position) {
            scope.entity.storageLocation = scope.entity.storageLocation || {};
            angular.extend(scope.entity.storageLocation, position);
            $timeout(function() {
              angular.extend(scope.entity.storageLocation, position);
            });
          }
        );
      };

      scope.searchContainer = function(name) {
        loadContainers(name, scope);
      };

      watchOccupyingEntityChanges(scope);
    };

    return {
      restrict: 'E',

      replace: true,

      priority: 100,

      terminal: true,

      scope: {
        entity: '=',
        cpId: '=',
        containerListCache: '=?'
      },

      compile: function(tElem, tAttrs) {
        var select = tElem.find('os-select');
        var input = tElem.find('input');

        if (tAttrs.hasOwnProperty('osMdInput')) {
          var button = tElem.find('button');

          select.attr('os-md-input', '');
          input.attr('os-md-input', '');

          if (tAttrs.hasOwnProperty('editWhen')) {
            select.attr('edit-when', tAttrs.editWhen);
            input.attr('edit-when', tAttrs.editWhen);
            button.attr('ng-if', tAttrs.editWhen);
          }

          //
          // make button smaller in size
          // ensure button is aligned with other text fields;
          // 15 px is used to display labels for os-md-input fields
          //
          button.addClass('btn-xs');
          if (!tAttrs.hasOwnProperty('hidePlaceholder')) {
            button.css('margin-top', '15px');
          }
        }

        if (tAttrs.hasOwnProperty('hidePlaceholder')) {
          select.removeAttr('placeholder');
          input.removeAttr('placeholder');
        }

        return linker;
      },

      templateUrl: 'modules/common/storage-position.html'
    }
  });

<|endoftext|>


<commit_before>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? '5' : '20');

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var timeoutPromise = null;

		var watch = function() {
			if( timeoutPromise ){
				$timeout.cancel( timeoutPromise );
			}

			timeoutPromise = $timeout(function(){
													if (previous == getQuery()) {
														return;
													}

													if (!previous) {
														$location.search(scope.query).replace();
													} else {
														$location.search(scope.query);
													}

													previous = getQuery();
													update();
											}, 1500 );
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<commit_msg>fixes #7264<commit_after>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? '5' : '20');

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var timeoutPromise = null;

		var watch = function() {
			if( timeoutPromise ){
				$timeout.cancel( timeoutPromise );
			}

			timeoutPromise = $timeout(function(){
													if (previous == getQuery()) {
														return;
													}

													if (!previous) {
														$location.search(scope.query).replace();
													} else {
														$location.search(scope.query);
													}

													previous = getQuery();
													update();
											}, 10 );
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<|endoftext|>


<commit_before>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? '5' : '20');

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var watch = function() {
			if (previous == getQuery()) {
				return;
			}

			if (!previous) {
				$location.search(scope.query).replace();
			} else {
				$location.search(scope.query);
			}

			previous = getQuery();
			update();
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<commit_msg>Communities page is super slow #7203<commit_after>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? '5' : '20');

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var timeoutPromise = null;

		var watch = function() {
			if( timeoutPromise ){
				$timeout.cancel( timeoutPromise );
			}

			timeoutPromise = $timeout(function(){
													if (previous == getQuery()) {
														return;
													}

													if (!previous) {
														$location.search(scope.query).replace();
													} else {
														$location.search(scope.query);
													}

													previous = getQuery();
													update();
											}, 1500 );
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<|endoftext|>


<commit_before>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? 5 : 20);

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var watch = function() {
			if (previous == getQuery()) {
				return;
			}

			previous = getQuery();
			$location.search(scope.query);
			update();
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<commit_msg>fixes back button on list views<commit_after>
NGApp.factory('ViewListService', function($location, $timeout) {

	var service = {};

	service.view = function(params) {
		var scope = params.scope;
		var query = $location.search();
		var defaultLimit = query.limit || (App.isMobile() ? 5 : 20);

		scope.query = {
			limit: defaultLimit,
			page: query.page || 1,
			fullcount: true
		};
		scope.query.page = parseInt(scope.query.page);

		var previous = null;
		var getQuery = function() {
			var q = '';
			for (var x in scope.query) {
				q += x + scope.query[x];
			}
			return q;
		};

		var watch = function() {
			if (previous == getQuery()) {
				return;
			}

			previous = getQuery();
			$location.search(scope.query).replace();
			update();
		};

		// @todo: this breaks linking to pages
		var inputWatch = function() {
			if (scope.query.page != 1) {
				scope.query.page = 1;
			} else {
				watch();
			}
		};

		scope.watch = function(vars) {
			for (var x in vars) {
				scope.query[x] = query[x] || vars[x];
				if( x ){
					scope.$watch('query.' + x, inputWatch);
				}
			}
		};

		scope.count = 0;
		scope.pages = 0;
		scope.more = false;

		scope.allowAll = params.allowAll ? true : false;

		scope.$watch('query.limit', inputWatch);
		scope.$watch('query.page', watch);

		scope.setPage = function(page) {
			scope.query.page = page;
			App.scrollTop(0);
		};

		scope.viewAll = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = 'none';
		};

		scope.viewLess = function() {
			if (!scope.allowAll) {
				return;
			}
			scope.query.page = 1;
			scope.query.limit = defaultLimit;
		};

		scope.sort = function(by) {
			if (scope.query.sort == by) {
				scope.query.sort = '-' + by;
			} else {
				scope.query.sort = by;
			}
		};

		var updater = function(){};

		scope.update = function(fn) {
			if (fn) {
				updater = fn;
			} else {
				update();
			}
		};

		scope.loader = false;

		scope.complete = function(d) {
			scope.count = d.count;
			scope.pages = d.pages;
			scope.more = d.more;

			if (scope.loader) {
				clearTimeout(scope.loader);
				scope.loader = setTimeout(function() {
					scope.scope.$apply(function() {
						scope.loading = false;
					});
				},100);
			} else {
				scope.loading = false;
			}
		};

		var update = function() {
			scope.loading = true;
			updater();
		};

		if (!App.isPhoneGap) {
			scope.focus('#search');
		}

		scope.watch(params.watch);
		scope.update(params.update);
	}

	return service;
});
<|endoftext|>


<commit_before>/**
 * @namespace ImageHelpers
 */
export default {

  /**
   * Generates the image src for a resized image with maximum dimensions `maxWidth` and `maxHeight`.
   * Images do not scale up.
   *
   * @example
   * const url = client.image.imageForSize(product.variants[0].image, {maxWidth: 50, maxHeight: 50});
   *
   * @memberof ImageHelpers
   * @method imageForSize
   * @param {Object} image The original image model to generate the image src for.
   * @param {Object} options An options object containing:
   *  @param {Integer} options.maxWidth The maximum width for the image.
   *  @param {Integer} options.maxHeight The maximum height for the image.
   * @return {String} The image src for the resized image.
   */
  imageForSize(image, {maxWidth, maxHeight}) {
    const splitUrl = image.src.split('?');
    const notQuery = splitUrl[0];
    const query = splitUrl[1] ? `?${splitUrl[1]}` : '';

    // Use the section before the query
    const imageTokens = notQuery.split('.');

    // Take the token before the file extension and append the dimensions
    const imagePathIndex = imageTokens.length - 2;

    imageTokens[imagePathIndex] = `${imageTokens[imagePathIndex]}_${maxWidth}x${maxHeight}`;

    return `${imageTokens.join('.')}${query}`;
  }
};
<commit_msg>Adjust example code for imageForSize helper<commit_after>/**
 * @namespace ImageHelpers
 */
export default {

  /**
   * Generates the image src for a resized image with maximum dimensions `maxWidth` and `maxHeight`.
   * Images do not scale up.
   *
   * @example
   * const url = client.image.helpers.imageForSize(product.variants[0].image, {maxWidth: 50, maxHeight: 50});
   *
   * @memberof ImageHelpers
   * @method imageForSize
   * @param {Object} image The original image model to generate the image src for.
   * @param {Object} options An options object containing:
   *  @param {Integer} options.maxWidth The maximum width for the image.
   *  @param {Integer} options.maxHeight The maximum height for the image.
   * @return {String} The image src for the resized image.
   */
  imageForSize(image, {maxWidth, maxHeight}) {
    const splitUrl = image.src.split('?');
    const notQuery = splitUrl[0];
    const query = splitUrl[1] ? `?${splitUrl[1]}` : '';

    // Use the section before the query
    const imageTokens = notQuery.split('.');

    // Take the token before the file extension and append the dimensions
    const imagePathIndex = imageTokens.length - 2;

    imageTokens[imagePathIndex] = `${imageTokens[imagePathIndex]}_${maxWidth}x${maxHeight}`;

    return `${imageTokens.join('.')}${query}`;
  }
};
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');

const Couch = require('../index');
const debug = require('../util/debug')('import');
const getConfig = require('../config/config').getConfig;

exports.import = function (database, importName, file) {
    debug(`import ${file} (${database}, ${importName})`);

    const filename = path.parse(file).base;
    let contents = fs.readFileSync(file);

    let config = getConfig(database);
    if (!config.import || !config.import[importName]) {
        throw new Error(`no import config for ${database}/${importName}`);
    }
    config = config.import[importName];

    const couch = Couch.get(database);

    // Callbacks
    const getID = verifyConfig('getID', null, true);
    const getOwner = verifyConfig('getOwner', null, true);
    let parse = null;
    let json = null;
    try {
        parse = verifyConfig('parse', null, true);
    } catch (e) {
        json = verifyConfig('json', null, true);
    }

    if (json) contents = JSON.parse(contents);

    return Promise.resolve()
        .then(getMetadata)
        .then(parseFile)
        .then(getKind)
        .then(checkDocumentExists)
        .then(updateDocument)
        .then(function () {
            debug.trace(`import ${file} success`);
            couch.log(`Import ${file} ok`, 'WARN');
        }).catch(function (e) {
            debug.error(`import ${file} failure: ${e.message}, ${e.stack}`);
            couch.log(`Import ${file} failed: ${e.message}`, 'ERROR');
            throw e;
        });

    function verifyConfig(name, defaultValue, mustBeFunction) {
        const value = config[name];
        if (value === undefined) {
            if (defaultValue) {
                return defaultValue;
            }
            throw new Error('missing configuration value: ' + name);
        }
        if (mustBeFunction && typeof value !== 'function') {
            throw new Error(`configuration value ${name} must be a function`);
        }
        return value;
    }

    function getMetadata() {
        debug.trace('get metadata');
        const id = Promise.resolve(getID(filename, contents, couch));
        const owner = Promise.resolve(getOwner(filename, contents, couch));
        return Promise.all([id, owner]).then(function (result) {
            debug.trace(`id: ${result[0]}, owner: ${result[1]}`);
            let owner = result[1];
            let owners;
            if (Array.isArray(owner)) {
                owners = owner;
                owner = owners[0];
                owners = owners.slice(1);
            }
            return {id: result[0], owner: owner, owners: owners};
        });
    }

    function getKind(info) {
        debug.trace('getKind');
        if (!config.kind) return info;
        if (! (typeof config.kind === 'function')) {
            info.kind = config.kind;
            return info;
        }
        return Promise.resolve(config.kind(filename, contents, couch)).then(function (kind) {
            info.kind = kind;
            return info;
        });
    }

    function parseFile(info) {
        debug.trace('parse file contents');
        if (parse) {
            return Promise.resolve(parse(filename, contents, couch)).then(function (result) {
                if (typeof result.jpath !== 'string') {
                    throw new Error('parse: jpath must be a string');
                }
                if (typeof result.data !== 'object' || result.data === null) {
                    throw new Error('parse: data must be an object');
                }
                if (typeof result.field !== 'string') {
                    throw new Error('parse: field must be a string');
                }

                debug.trace(`jpath: ${result.jpath}`);
                info.jpath = result.jpath.split('.');
                info.data = result.data;
                info.content_type = result.content_type || 'application/octet-stream';
                info.field = result.field;
                info.reference = result.reference;
                return info;
            });
        } else if (json) {
            return Promise.resolve(json(filename, contents, couch)).then(function (result) {
                info.data = result;
                return info;
            });
        }
    }

    function checkDocumentExists(info) {
        debug.trace('checkDocumentExists');
        return couch.createEntry(info.id, info.owner, {
            createParameters: [filename, contents],
            kind: info.kind,
            owners: info.owners
        }).then(docInfo => {
            return {
                info,
                docInfo
            };
        });
    }

    function updateDocument(info) {
        debug.trace('updateDocument');
        if (parse) {
            info = info.info;
            return couch.addFileToJpath(info.id, info.owner, info.jpath, info.data, {
                field: info.field,
                reference: info.reference,
                name: info.jpath.join('/') + '/' + filename,
                data: contents,
                content_type: info.content_type
            });
        }
        else if (json) {
            var entry = {};
            entry.$id = info.info.id;
            entry.$kind = config.kind;
            entry.$content = info.info.data;
            entry._id = info.docInfo.id;
            entry._rev = info.docInfo.rev;
            return couch.insertEntry(entry, info.info.owner, {
                merge: true
            });
        }
    }
};
<commit_msg>refactor(import): simplify condition in getKind<commit_after>'use strict';

const fs = require('fs');
const path = require('path');

const Couch = require('../index');
const debug = require('../util/debug')('import');
const getConfig = require('../config/config').getConfig;

exports.import = function (database, importName, file) {
    debug(`import ${file} (${database}, ${importName})`);

    const filename = path.parse(file).base;
    let contents = fs.readFileSync(file);

    let config = getConfig(database);
    if (!config.import || !config.import[importName]) {
        throw new Error(`no import config for ${database}/${importName}`);
    }
    config = config.import[importName];

    const couch = Couch.get(database);

    // Callbacks
    const getID = verifyConfig('getID', null, true);
    const getOwner = verifyConfig('getOwner', null, true);
    let parse = null;
    let json = null;
    try {
        parse = verifyConfig('parse', null, true);
    } catch (e) {
        json = verifyConfig('json', null, true);
    }

    if (json) contents = JSON.parse(contents);

    return Promise.resolve()
        .then(getMetadata)
        .then(parseFile)
        .then(getKind)
        .then(checkDocumentExists)
        .then(updateDocument)
        .then(function () {
            debug.trace(`import ${file} success`);
            couch.log(`Import ${file} ok`, 'WARN');
        }).catch(function (e) {
            debug.error(`import ${file} failure: ${e.message}, ${e.stack}`);
            couch.log(`Import ${file} failed: ${e.message}`, 'ERROR');
            throw e;
        });

    function verifyConfig(name, defaultValue, mustBeFunction) {
        const value = config[name];
        if (value === undefined) {
            if (defaultValue) {
                return defaultValue;
            }
            throw new Error('missing configuration value: ' + name);
        }
        if (mustBeFunction && typeof value !== 'function') {
            throw new Error(`configuration value ${name} must be a function`);
        }
        return value;
    }

    function getMetadata() {
        debug.trace('get metadata');
        const id = Promise.resolve(getID(filename, contents, couch));
        const owner = Promise.resolve(getOwner(filename, contents, couch));
        return Promise.all([id, owner]).then(function (result) {
            debug.trace(`id: ${result[0]}, owner: ${result[1]}`);
            let owner = result[1];
            let owners;
            if (Array.isArray(owner)) {
                owners = owner;
                owner = owners[0];
                owners = owners.slice(1);
            }
            return {id: result[0], owner: owner, owners: owners};
        });
    }

    function getKind(info) {
        debug.trace('getKind');
        if (!config.kind) return info;
        if (typeof config.kind !== 'function') {
            info.kind = config.kind;
            return info;
        }
        return Promise.resolve(config.kind(filename, contents, couch)).then(function (kind) {
            info.kind = kind;
            return info;
        });
    }

    function parseFile(info) {
        debug.trace('parse file contents');
        if (parse) {
            return Promise.resolve(parse(filename, contents, couch)).then(function (result) {
                if (typeof result.jpath !== 'string') {
                    throw new Error('parse: jpath must be a string');
                }
                if (typeof result.data !== 'object' || result.data === null) {
                    throw new Error('parse: data must be an object');
                }
                if (typeof result.field !== 'string') {
                    throw new Error('parse: field must be a string');
                }

                debug.trace(`jpath: ${result.jpath}`);
                info.jpath = result.jpath.split('.');
                info.data = result.data;
                info.content_type = result.content_type || 'application/octet-stream';
                info.field = result.field;
                info.reference = result.reference;
                return info;
            });
        } else if (json) {
            return Promise.resolve(json(filename, contents, couch)).then(function (result) {
                info.data = result;
                return info;
            });
        }
    }

    function checkDocumentExists(info) {
        debug.trace('checkDocumentExists');
        return couch.createEntry(info.id, info.owner, {
            createParameters: [filename, contents],
            kind: info.kind,
            owners: info.owners
        }).then(docInfo => {
            return {
                info,
                docInfo
            };
        });
    }

    function updateDocument(info) {
        debug.trace('updateDocument');
        if (parse) {
            info = info.info;
            return couch.addFileToJpath(info.id, info.owner, info.jpath, info.data, {
                field: info.field,
                reference: info.reference,
                name: info.jpath.join('/') + '/' + filename,
                data: contents,
                content_type: info.content_type
            });
        }
        else if (json) {
            var entry = {};
            entry.$id = info.info.id;
            entry.$kind = config.kind;
            entry.$content = info.info.data;
            entry._id = info.docInfo.id;
            entry._rev = info.docInfo.rev;
            return couch.insertEntry(entry, info.info.owner, {
                merge: true
            });
        }
    }
};
<|endoftext|>


<commit_before>let clickedElement = null;

/**
  When user clicks somewhere on the page with Right mouse button - we save the
  clicked element in global variable(we will need it if user decides to scroll
  inside)
**/
document.addEventListener("mousedown", function(event){
    if(event.button == 2)
        clickedElement = event.target;
}, false);

/**
  The actual message listener when context menu is getting clicked
  @param object message = contains properties of the clicked CONTEXT_MENU
  element and action
**/
chrome.runtime.onMessage.addListener(message => {

	if (message.action && message.action == 'stop') {
		chrome.extension.sendMessage({
			type: 'notification',
			notification: {
				id: 'info',
				title: `Message`,
				text: `Lets stop for a sec...`
			}
		});
		return;
	}

	// if its a number (default 10 or 0 for user prompt)
	if ( !isNaN(message.times) ) {

		// if user selected N times
		if ( message.times === 0 ) {
			const userTimes = +prompt(chrome.i18n.getMessage("how_many_times"), 10);

			// if user didn't click the cancel button
			if(userTimes !== null)
				beforeScroll(message.direction, userTimes);
		}
		// user chose default 10 times
		else {
			beforeScroll(message.direction, message.times);
		}
	}
	// infinite times
	else {
		chrome.extension.sendMessage({
			type: 'notification',
			notification: {
				id: 'info',
				title: `Message`,
				text: `Infinite scroll will be ready soon!`
			}
		});
	}
});

/**
  Hook that runs before scrolling and launches it after
**/
function beforeScroll(direction, times) {

	// check if we are scrolling the instagram
	detectInstagram();

	// go go go!
	scroll(direction, times, closestScrollable(clickedElement));
}

/**
  Starts from element where user chose to scroll. If it's not scrollable - then
  go through all parents to the last <html> node and exit then
  If succeed: return node and max height of all these nodes
  @param node element = right-clicked element while opening a context menu
  @param int previousMaxHeight = max height of an element found during recursion
  @return object {node, maxHeight} or {false, maxHeight} if nothing has been found
**/
function closestScrollable(element, previousMaxHeight = 0) {
	let scrollableElement = element,
 			overflowY = window.getComputedStyle(element)['overflow-y'],
			maxHeight = element.clientHeight || 0;

	if (previousMaxHeight > maxHeight) {
		maxHeight = previousMaxHeight;
	}

	// checking if current element has overflow / scroll
	if (( overflowY === 'scroll' || overflowY === 'auto' ) &&
			( scrollableElement.scrollHeight > scrollableElement.clientHeight ))
		{
			// we got THE ONE
			return {
				node: scrollableElement,
				maxHeight: maxHeight
			};
		}
		else {

			// if he has a parent element - lets give him a try with recursion
			if (scrollableElement.parentElement)
				return closestScrollable(scrollableElement.parentElement, maxHeight);
			else
			// or let's just return the max height of elements and false instead of node
				return {
					node: false,
					maxHeight: maxHeight
				};
		}
}

/**
**/
function scroll(direction, total, closestScrollable) {
	// number of times we should scroll up/down
	total = parseInt(total) || 10;

	// iterator
	let doneTimes = 0;

	// interval to scroll again
	const interval = setInterval(() => {

		// if we found an element that can be scrolled
		if (closestScrollable.node) {
			if (direction == "up")
				closestScrollable.node.scrollTop -= closestScrollable.maxHeight;
			else
				closestScrollable.node.scrollTop += closestScrollable.maxHeight;
		}
		// try to use window by default
		else {
			if (direction == "up")
				window.scrollTo(0, -getWindowHeight());
			else
				window.scrollTo(0, getWindowHeight());
		}

		// check if we are done with iterations
		if (++doneTimes >= total) {
			clearInterval(interval);
			chrome.extension.sendMessage({
				type: 'notification',
				notification: {
					id: 'scrolling',
					title: `Job's done!`, // http://classic.battle.net/war3/images/orc/units/portraits/peon.gif
					text: `I scrolled ${direction} (${total} times) and idle now. \nClick me to switch to that tab.`
				}
			});
		}
	}, 500);
}

/**
  Check if current tab is an instagram website - click on "load more" button
  to scroll freely
**/
function detectInstagram() {
	if (window.location.href.includes('instagram')) {
		let anchor = _x(`//a[contains(@href, "${window.location.pathname}")]`);
		if (anchor && anchor[0]) {
			anchor[0].click();
		}
	}
}

function getWindowHeight() {
	const body = document.body,
				html = document.documentElement;

	return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight,
									 html.scrollHeight, html.offsetHeight );
}

/**
  Xpath helper
  @param string STR_XPATH = the actual xpath of searched element(s)
  @credits Thanks to https://stackoverflow.com/a/14669479/3687408
**/
function _x(STR_XPATH) {
    let xresult = document.evaluate(STR_XPATH, document, null, XPathResult.ANY_TYPE, null),
     		xnodes = [],
    		xres;

    while (xres = xresult.iterateNext()) {
        xnodes.push(xres);
    }

    return xnodes;
}
<commit_msg>Modified indents<commit_after>let clickedElement = null;

/**
  When user clicks somewhere on the page with Right mouse button - we save the
  clicked element in global variable(we will need it if user decides to scroll
  inside)
**/
document.addEventListener("mousedown", function(event){
    if(event.button == 2)
        clickedElement = event.target;
}, false);

/**
  The actual message listener when context menu is getting clicked
  @param object message = contains properties of the clicked CONTEXT_MENU
  element and action
**/
chrome.runtime.onMessage.addListener(message => {

	if (message.action && message.action == 'stop') {
		chrome.extension.sendMessage({
			type: 'notification',
			notification: {
				id: 'info',
				title: `Message`,
				text: `Lets stop for a sec...`
			}
		});
		return;
	}

	// if its a number (default 10 or 0 for user prompt)
	if ( !isNaN(message.times) ) {

		// if user selected N times
		if ( message.times === 0 ) {
			const userTimes = +prompt(chrome.i18n.getMessage("how_many_times"), 10);

			// if user didn't click the cancel button
			if(userTimes !== null)
				beforeScroll(message.direction, userTimes);
		}
		// user chose default 10 times
		else {
			beforeScroll(message.direction, message.times);
		}
	}
	// infinite times
	else {
		chrome.extension.sendMessage({
			type: 'notification',
			notification: {
				id: 'info',
				title: `Message`,
				text: `Infinite scroll will be ready soon!`
			}
		});
	}
});

/**
  Hook that runs before scrolling and launches it after
**/
function beforeScroll(direction, times) {

	// check if we are scrolling the instagram
	detectInstagram();

	// go go go!
	scroll(direction, times, closestScrollable(clickedElement));
}

/**
  Starts from element where user chose to scroll. If it's not scrollable - then
  go through all parents to the last <html> node and exit then
  If succeed: return node and max height of all these nodes
  @param node element = right-clicked element while opening a context menu
  @param int previousMaxHeight = max height of an element found during recursion
  @return object {node, maxHeight} or {false, maxHeight} if nothing has been found
**/
function closestScrollable(element, previousMaxHeight = 0) {
	let scrollableElement = element,
			overflowY = window.getComputedStyle(element)['overflow-y'],
      maxHeight = element.clientHeight || 0;

	if (previousMaxHeight > maxHeight) {
		maxHeight = previousMaxHeight;
	}

	// checking if current element has overflow / scroll
	if (( overflowY === 'scroll' || overflowY === 'auto' ) &&
      ( scrollableElement.scrollHeight > scrollableElement.clientHeight ))
		{
			// we got THE ONE
			return {
				node: scrollableElement,
				maxHeight: maxHeight
			};
		}
		else {

			// if he has a parent element - lets give him a try with recursion
			if (scrollableElement.parentElement)
				return closestScrollable(scrollableElement.parentElement, maxHeight);
			else
			// or let's just return the max height of elements and false instead of node
				return {
					node: false,
					maxHeight: maxHeight
				};
		}
}

/**
**/
function scroll(direction, total, closestScrollable) {
	// number of times we should scroll up/down
	total = parseInt(total) || 10;

	// iterator
	let doneTimes = 0;

	// interval to scroll again
	const interval = setInterval(() => {

		// if we found an element that can be scrolled
		if (closestScrollable.node) {
			if (direction == "up")
				closestScrollable.node.scrollTop -= closestScrollable.maxHeight;
			else
				closestScrollable.node.scrollTop += closestScrollable.maxHeight;
		}
		// try to use window by default
		else {
			if (direction == "up")
				window.scrollTo(0, -getWindowHeight());
			else
				window.scrollTo(0, getWindowHeight());
		}

		// check if we are done with iterations
		if (++doneTimes >= total) {
			clearInterval(interval);
			chrome.extension.sendMessage({
				type: 'notification',
				notification: {
					id: 'scrolling',
					title: `Job's done!`, // http://classic.battle.net/war3/images/orc/units/portraits/peon.gif
					text: `I scrolled ${direction} (${total} times) and idle now. \nClick me to switch to that tab.`
				}
			});
		}
	}, 500);
}

/**
  Check if current tab is an instagram website - click on "load more" button
  to scroll freely
**/
function detectInstagram() {
	if (window.location.href.includes('instagram')) {
		let anchor = _x(`//a[contains(@href, "${window.location.pathname}")]`);
		if (anchor && anchor[0]) {
			anchor[0].click();
		}
	}
}

function getWindowHeight() {
	const body = document.body,
				html = document.documentElement;

	return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight,
									 html.scrollHeight, html.offsetHeight );
}

/**
  Xpath helper
  @param string STR_XPATH = the actual xpath of searched element(s)
  @credits Thanks to https://stackoverflow.com/a/14669479/3687408
**/
function _x(STR_XPATH) {
    let xresult = document.evaluate(STR_XPATH, document, null, XPathResult.ANY_TYPE, null),
     		xnodes = [],
    		xres;

    while (xres = xresult.iterateNext()) {
        xnodes.push(xres);
    }

    return xnodes;
}
<|endoftext|>


<commit_before>chrome.extension.sendMessage({}, function(response) {
  var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
      clearInterval(readyStateCheckInterval);

      var observer = new MutationObserver(function (mutations) {
        mutations.forEach(handleMutationEvents);
      });

      // configuration of the observer:
      var config = {
        attributes: true,
        characterData: true,
        childList: true,
        subtree: true
      };

      observer.observe(document, config);

      var handleMutationEvents = function handleMutationEvents(mutation) {
        Array.prototype.forEach.call(mutation.addedNodes, styleLabelsInNode);
        styleLabelsInNode(mutation.target);
      }

      var styleLabelsInNode = function styleLabelsInNode(node) {
        if (nodeIsElement(node)) {
          styleLabels(findLabelsInNode(node));
        }
      }

      var nodeIsElement = function nodeIsElement(node) {
        return (typeof node.getElementsByClassName !== 'undefined');
      }

      var findLabelsInNode = function findLabelsInNode(node) {
        return node.querySelectorAll('a.label');
      }

      var styleLabels = function styleLabels(labels) {
        Array.prototype.forEach.call(labels, function(label) {
          if (isLabelEligible(label.textContent)) {
            label.classList.add('blocked');
          } else {
            label.classList.remove('blocked');
          }
        });
      }
    }
  }, 10);
});
<commit_msg>Test that nodes contain the methods we use<commit_after>chrome.extension.sendMessage({}, function(response) {
  var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
      clearInterval(readyStateCheckInterval);

      var observer = new MutationObserver(function (mutations) {
        mutations.forEach(handleMutationEvents);
      });

      // configuration of the observer:
      var config = {
        attributes: true,
        characterData: true,
        childList: true,
        subtree: true
      };

      observer.observe(document, config);

      var handleMutationEvents = function handleMutationEvents(mutation) {
        Array.prototype.forEach.call(mutation.addedNodes, styleLabelsInNode);
        styleLabelsInNode(mutation.target);
      }

      var styleLabelsInNode = function styleLabelsInNode(node) {
        if (nodeIsElement(node)) {
          styleLabels(findLabelsInNode(node));
        }
      }

      var nodeIsElement = function nodeIsElement(node) {
        return (typeof node.querySelectorAll !== 'undefined');
      }

      var findLabelsInNode = function findLabelsInNode(node) {
        return node.querySelectorAll('a.label');
      }

      var styleLabels = function styleLabels(labels) {
        Array.prototype.forEach.call(labels, function(label) {
          if (isLabelEligible(label.textContent)) {
            label.classList.add('blocked');
          } else {
            label.classList.remove('blocked');
          }
        });
      }
    }
  }, 10);
});
<|endoftext|>