aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/exclusions.coffee2
-rw-r--r--pages/options.coffee63
-rw-r--r--pages/options.css230
-rw-r--r--pages/options.html237
-rw-r--r--pages/popup.html115
5 files changed, 340 insertions, 307 deletions
diff --git a/background_scripts/exclusions.coffee b/background_scripts/exclusions.coffee
index 2b34238b..ac0e5f20 100644
--- a/background_scripts/exclusions.coffee
+++ b/background_scripts/exclusions.coffee
@@ -18,6 +18,8 @@ RegexpCache =
# The exclusions are an array of such objects (because the order matters).
root.Exclusions = Exclusions =
+ # Make RegexpCache, which is required on the page popup, accessible via Exclusions.
+ RegexpCache: RegexpCache
rules: Settings.get("exclusionRules")
diff --git a/pages/options.coffee b/pages/options.coffee
index cd19fa37..776432d2 100644
--- a/pages/options.coffee
+++ b/pages/options.coffee
@@ -1,6 +1,6 @@
-
$ = (id) -> document.getElementById id
bgSettings = chrome.extension.getBackgroundPage().Settings
+Exclusions = chrome.extension.getBackgroundPage().Exclusions
#
# Class hierarchy for various types of option.
@@ -13,6 +13,7 @@ class Option
constructor: (field,enableSaveButton) ->
@field = field
+ @onUpdated = enableSaveButton
@element = $(@field)
@element.addEventListener "change", enableSaveButton
@fetch()
@@ -41,8 +42,10 @@ class Option
# Static method.
@saveOptions: ->
Option.all.map (option) -> option.save()
- $("saveOptions").disabled = true
- $("saveOptions").innerHTML = "No Changes"
+ # These are only relevant on the options page; catch the exception on the popup page.
+ try
+ $("saveOptions").disabled = true
+ $("saveOptions").innerHTML = "No Changes"
# Abstract method; only implemented in sub-classes.
# Populate the option's DOM element (@element) with the setting's current value.
@@ -77,8 +80,8 @@ class CheckBoxOption extends Option
readValueFromElement: -> @element.checked
class ExclusionRulesOption extends Option
- constructor: (args...) ->
- super(args...)
+ constructor: (field, onUpdated, @url=null) ->
+ super(field, onUpdated)
$("exclusionAddButton").addEventListener "click", (event) =>
@appendRule { pattern: "", passKeys: "" }
# Focus the pattern element in the new rule.
@@ -91,6 +94,16 @@ class ExclusionRulesOption extends Option
for rule in rules
@appendRule rule
+ # If this is the popup page (@url is defined), then hide rules which do not match @url. If no rules
+ # match, then add a default rule.
+ if @url
+ haveMatch = false
+ for element in @element.getElementsByClassName "exclusionRuleTemplateInstance"
+ pattern = element.children[0].firstChild.value.trim()
+ unless @url.match Exclusions.RegexpCache.get pattern
+ element.style.display = 'none'
+ haveMatch = true
+
# Append a row for a new rule.
appendRule: (rule) ->
content = document.querySelector('#exclusionRuleTemplate').content
@@ -100,13 +113,13 @@ class ExclusionRulesOption extends Option
element = row.querySelector ".#{field}"
element.value = rule[field]
for event in [ "input", "change" ]
- element.addEventListener event, enableSaveButton
+ element.addEventListener event, @onUpdated
remove = row.querySelector ".exclusionRemoveButton"
remove.addEventListener "click", (event) =>
row = event.target.parentNode.parentNode
row.parentNode.removeChild row
- enableSaveButton()
+ @onUpdated()
@element.appendChild row
@@ -160,12 +173,8 @@ activateHelpDialog = ->
# Prevent the "show help" link from retaining the focus.
document.activeElement.blur()
-#
-# Initialization.
-document.addEventListener "DOMContentLoaded", ->
-
- # Populate options. The constructor adds each new object to "Option.all".
- new type(name,enableSaveButton) for name, type of {
+initOptions = ->
+ options =
exclusionRules: ExclusionRulesOption
filterLinkHints: CheckBoxOption
hideHud: CheckBoxOption
@@ -181,7 +190,10 @@ document.addEventListener "DOMContentLoaded", ->
searchEngines: TextOption
searchUrl: NonEmptyTextOption
userDefinedLinkHintCss: TextOption
- }
+
+ # Populate options. The constructor adds each new object to "Option.all".
+ for name, type of options
+ new type(name,enableSaveButton)
$("saveOptions").addEventListener "click", Option.saveOptions
$("advancedOptionsLink").addEventListener "click", toggleAdvancedOptions
@@ -200,3 +212,26 @@ document.addEventListener "DOMContentLoaded", ->
document.activeElement.blur() if document?.activeElement?.blur
Option.saveOptions()
+initPopup = ->
+ chrome.tabs.getSelected null, (tab) ->
+ document.getElementById("optionsLink").setAttribute "href", chrome.runtime.getURL("pages/options.html")
+ updated = false
+
+ onUpdated = ->
+ $("helpText").innerHTML = "Type <strong>Ctrl-Enter</strong> to save and close; <strong>Esc</strong> to cancel."
+ updated = true
+
+ document.addEventListener "keyup", (event) ->
+ if event.ctrlKey and event.keyCode == 13
+ Option.saveOptions()
+ window.close()
+
+ new ExclusionRulesOption("exclusionRules", onUpdated, tab.url)
+
+#
+# Initialization.
+document.addEventListener "DOMContentLoaded", ->
+ switch location.pathname
+ when "/pages/options.html" then initOptions()
+ when "/pages/popup.html" then initPopup()
+
diff --git a/pages/options.css b/pages/options.css
new file mode 100644
index 00000000..148d1330
--- /dev/null
+++ b/pages/options.css
@@ -0,0 +1,230 @@
+body {
+ font: 14px "DejaVu Sans", "Arial", sans-serif;
+ color: #303942;
+ margin: 0 auto;
+}
+a, a:visited { color: #15c; }
+a:active { color: #052577; }
+div#wrapper, #footerWrapper {
+ width: 540px;
+ margin-left: 35px;
+}
+header {
+ font-size: 18px;
+ font-weight: normal;
+ border-bottom: 1px solid #eee;
+ padding: 20px 0 15px 0;
+ width: 100%;
+}
+button {
+ -webkit-user-select: none;
+ -webkit-appearance: none;
+ background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+ border-radius: 2px;
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
+ color: #444;
+ font: inherit;
+ text-shadow: 0 1px 0 #f0f0f0;
+ height: 24px;
+ font-size: 12px;
+ padding: 0 10px;
+}
+button:hover {
+ background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
+ border-color: rgba(0, 0, 0, 0.3);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95);
+ color: black;
+}
+button:active {
+ background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
+ box-shadow: none;
+ text-shadow: none;
+}
+button[disabled], button[disabled]:hover, button[disabled]:active {
+ background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
+ text-shadow: 0 1px 0 #f0f0f0;
+ color: #888;
+}
+input[type="checkbox"] {
+ -webkit-user-select: none;
+}
+label:hover {
+ color: black;
+}
+pre, code, .code {
+ font-family: Consolas, "Liberation Mono", Courier, monospace;
+}
+pre {
+ margin: 5px;
+ border-left: 1px solid #eee;
+ padding-left: 5px;
+
+}
+input, textarea {
+ box-sizing: border-box;
+}
+textarea {
+ /* Horizontal resizing is pretty screwy-looking. */
+ resize: vertical;
+}
+table#options{
+ width: 100%;
+ font-size: 14px;
+ position: relative;
+ border-spacing: 0 23px;
+}
+.example {
+ font-size: 12px;
+ line-height: 16px;
+ color: #979ca0;
+ margin-left: 20px;
+}
+.info {
+ margin-left: 0px;
+}
+.caption {
+ margin-right: 10px;
+ min-width: 130px;
+ padding-top: 3px;
+ vertical-align: top;
+}
+td { padding: 0; }
+div#exampleKeyMapping {
+ margin-left: 10px;
+ margin-top: 5px;
+}
+input#linkHintCharacters {
+ width: 100%;
+}
+input#linkHintNumbers {
+ width: 100%;
+}
+input#linkHintCharacters {
+ width: 100%;
+}
+input#scrollStepSize {
+ width: 40px;
+ margin-right: 3px;
+}
+textarea#userDefinedLinkHintCss, textarea#keyMappings, textarea#searchEngines {
+ width: 100%;;
+ min-height: 130px;
+ white-space: nowrap;
+}
+input#previousPatterns, input#nextPatterns {
+ width: 100%;
+}
+input#newTabUrl {
+ width: 100%;
+}
+input#searchUrl {
+ width: 100%;
+}
+#status {
+ margin-left: 10px;
+ font-size: 80%;
+}
+/* Make the caption in the settings table as small as possible, to pull the other fields to the right. */
+.caption {
+ width: 1px;
+ white-space: nowrap;
+}
+#buttonsPanel { width: 100%; }
+#advancedOptions { display: none; }
+#advancedOptionsLink { line-height: 24px; }
+.help {
+ position: absolute;
+ right: -320px;
+ width: 320px;
+}
+input:read-only {
+ background-color: #eee;
+ color: #666;
+ pointer-events: none;
+ -webkit-user-select: none;
+}
+input[type="text"], textarea {
+ border: 1px solid #bfbfbf;
+ border-radius: 2px;
+ color: #444;
+ font: inherit;
+ padding: 3px;
+}
+button:focus, input[type="text"]:focus, textarea:focus {
+ -webkit-transition: border-color 200ms;
+ border-color: #4d90fe;
+ outline: none;
+}
+/* Boolean options have a tighter form representation than text options. */
+td.booleanOption { font-size: 12px; }
+/* Ids and classes for rendering exclusionRules */
+#exclusionScrollBox {
+ overflow: scroll;
+ overflow-x: hidden;
+ overflow-y: auto;
+ /* Each exclusion rule is about 30px, so this allows 7 before scrolling */
+ max-height: 215px;
+ min-height: 75px;
+ border-radius: 2px;
+ color: #444;
+ width: 100%
+}
+#exclusionRules {
+ width: 100%;
+}
+.exclusionRulePassKeys {
+ width: 33%;
+}
+.exclusionRemoveButton {
+ width: 1px; /* 1px; smaller than the button itself. */
+}
+.exclusionRemoveButtonButton {
+ border: none;
+ background-color: #fff;
+ color: #979ca0;
+}
+.exclusionRemoveButtonButton:hover {
+ color: #444;
+}
+input.pattern, input.passKeys, .exclusionHeaderText {
+ width: 100%;
+ font-family: Consolas, "Liberation Mono", Courier, monospace;
+ font-size: 14px;
+}
+.exclusionHeaderText {
+ padding-left: 3px;
+ color: #979ca0;
+}
+#exclusionAddButton {
+ float: right;
+ margin-right: 0px;
+ margin-top: 5px;
+}
+#footer {
+ background: #f5f5f5;
+ border-top: 1px solid #979ca0;
+ position: fixed;
+ bottom: 0px;
+ z-index: 10;
+}
+#footer, #footerTable, #footerTableData {
+ width: 100%;
+}
+#endSpace {
+ /* Leave space for the fixed footer. */
+ min-height: 30px;
+ max-height: 30px;
+}
+#helpText {
+ font-size: 12px;
+}
+#saveOptionsTableData {
+ float: right;
+}
+#saveOptions {
+ white-space: nowrap;
+ width: 110px;
+}
diff --git a/pages/options.html b/pages/options.html
index 8e685304..03016d3f 100644
--- a/pages/options.html
+++ b/pages/options.html
@@ -1,242 +1,9 @@
<html>
<head>
<title>Vimium Options</title>
+ <link rel="stylesheet" type="text/css" href="options.css">
<script src="content_script_loader.js"></script>
- <style type="text/css" media="screen">
- body {
- font: 14px "DejaVu Sans", "Arial", sans-serif;
- color: #303942;
- margin: 0 auto;
- }
- a, a:visited { color: #15c; }
- a:active { color: #052577; }
- div#wrapper, #footerWrapper {
- width: 540px;
- margin-left: 35px;
- }
- header {
- font-size: 18px;
- font-weight: normal;
- border-bottom: 1px solid #eee;
- padding: 20px 0 15px 0;
- width: 100%;
- }
- button {
- -webkit-user-select: none;
- -webkit-appearance: none;
- background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
- border: 1px solid rgba(0, 0, 0, 0.25);
- border-radius: 2px;
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
- color: #444;
- font: inherit;
- text-shadow: 0 1px 0 #f0f0f0;
- height: 24px;
- font-size: 12px;
- padding: 0 10px;
- }
- button:hover {
- background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
- border-color: rgba(0, 0, 0, 0.3);
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95);
- color: black;
- }
- button:active {
- background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
- box-shadow: none;
- text-shadow: none;
- }
- button[disabled], button[disabled]:hover, button[disabled]:active {
- background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
- border: 1px solid rgba(0, 0, 0, 0.25);
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
- text-shadow: 0 1px 0 #f0f0f0;
- color: #888;
- }
- input[type="checkbox"] {
- -webkit-user-select: none;
- }
- label:hover {
- color: black;
- }
- pre, code, .code {
- font-family: Consolas, "Liberation Mono", Courier, monospace;
- }
- pre {
- margin: 5px;
- border-left: 1px solid #eee;
- padding-left: 5px;
-
- }
- input, textarea {
- box-sizing: border-box;
- }
- textarea {
- /* Horizontal resizing is pretty screwy-looking. */
- resize: vertical;
- }
- table#options{
- width: 100%;
- font-size: 14px;
- position: relative;
- border-spacing: 0 23px;
- }
- .example {
- font-size: 12px;
- line-height: 16px;
- color: #979ca0;
- margin-left: 20px;
- }
- .info {
- margin-left: 0px;
- }
- .caption {
- margin-right: 10px;
- min-width: 130px;
- padding-top: 3px;
- vertical-align: top;
- }
- td { padding: 0; }
- div#exampleKeyMapping {
- margin-left: 10px;
- margin-top: 5px;
- }
- input#linkHintCharacters {
- width: 100%;
- }
- input#linkHintNumbers {
- width: 100%;
- }
- input#linkHintCharacters {
- width: 100%;
- }
- input#scrollStepSize {
- width: 40px;
- margin-right: 3px;
- }
- textarea#userDefinedLinkHintCss, textarea#keyMappings, textarea#searchEngines {
- width: 100%;;
- min-height: 130px;
- white-space: nowrap;
- }
- input#previousPatterns, input#nextPatterns {
- width: 100%;
- }
- input#newTabUrl {
- width: 100%;
- }
- input#searchUrl {
- width: 100%;
- }
- #status {
- margin-left: 10px;
- font-size: 80%;
- }
- /* Make the caption in the settings table as small as possible, to pull the other fields to the right. */
- .caption {
- width: 1px;
- white-space: nowrap;
- }
- #buttonsPanel { width: 100%; }
- #advancedOptions { display: none; }
- #advancedOptionsLink { line-height: 24px; }
- .help {
- position: absolute;
- right: -320px;
- width: 320px;
- }
- input:read-only {
- background-color: #eee;
- color: #666;
- pointer-events: none;
- -webkit-user-select: none;
- }
- input[type="text"], textarea {
- border: 1px solid #bfbfbf;
- border-radius: 2px;
- color: #444;
- font: inherit;
- padding: 3px;
- }
- button:focus, input[type="text"]:focus, textarea:focus {
- -webkit-transition: border-color 200ms;
- border-color: #4d90fe;
- outline: none;
- }
- /* Boolean options have a tighter form representation than text options. */
- td.booleanOption { font-size: 12px; }
- /* Ids and classes for rendering exclusionRules */
- #exclusionScrollBox {
- overflow: scroll;
- overflow-x: hidden;
- overflow-y: auto;
- /* Each exclusion rule is about 30px, so this allows 7 before scrolling */
- max-height: 215px;
- min-height: 75px;
- border-radius: 2px;
- color: #444;
- width: 100%
- }
- #exclusionRules {
- width: 100%;
- }
- .exclusionRulePassKeys {
- width: 33%;
- }
- .exclusionRemoveButton {
- width: 1px; /* 1px; smaller than the button itself. */
- }
- .exclusionRemoveButtonButton {
- border: none;
- background-color: #fff;
- color: #979ca0;
- }
- .exclusionRemoveButtonButton:hover {
- color: #444;
- }
- input.pattern, input.passKeys, .exclusionHeaderText {
- width: 100%;
- font-family: Consolas, "Liberation Mono", Courier, monospace;
- font-size: 14px;
- }
- .exclusionHeaderText {
- padding-left: 3px;
- color: #979ca0;
- }
- #exclusionAddButton {
- float: right;
- margin-right: 0px;
- margin-top: 5px;
- }
- #footer {
- background: #f5f5f5;
- border-top: 1px solid #979ca0;
- position: fixed;
- bottom: 0px;
- z-index: 10;
- }
- #footer, #footerTable, #footerTableData {
- width: 100%;
- }
- #endSpace {
- /* Leave space for the fixed footer. */
- min-height: 30px;
- max-height: 30px;
- }
- #helpText {
- font-size: 12px;
- }
- #saveOptionsTableData {
- float: right;
- }
- #saveOptions {
- white-space: nowrap;
- width: 110px;
- }
- </style>
-
- <script type="text/javascript" src="options.js"></script>
-
+ <script type="text/javascript" src="options.js"></script>
</head>
<body>
diff --git a/pages/popup.html b/pages/popup.html
index 775d6c07..726ecc3f 100644
--- a/pages/popup.html
+++ b/pages/popup.html
@@ -1,85 +1,84 @@
<html>
<head>
+ <link rel="stylesheet" type="text/css" href="options.css">
<style>
* {
margin: 0px;
padding: 0px;
}
- #vimiumPopup { width: 400px; }
-
- #excludeControls {
- padding: 10px;
+ #endSpace {
+ width: 450px;
}
- #popupPattern, #popupPassKeys {
- margin: 5px;
- width: 330px;
- /* Match the corresponding font and font size used on the options page. */
- /* TODO (smblott): Match other styles from the options page. */
- font-family: Consolas, "Liberation Mono", Courier, monospace;
- font-size: 14px;
+ #helpText, #optionsLink {
+ font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
+ font-size: 12px;
}
- #confirmationMessage {
- display: inline-block;
- width: 18px;
- height: 13px;
- background: url(icons/check.png) 3px 2px no-repeat;
- display: none;
+ #helpText {
+ color: #979ca0;
}
- #popupRemove { margin: 5px; }
- #popupExclude { margin: 5px; }
-
- #popupMenu ul {
- list-style: none;
+ #exclusionAddButton {
+ width: 80px;
}
- #popupMenu li, #popupMenu a:active, #popupMenu a:visited {
- color: #3F6EC2;
- display: block;
- border-top: 1px solid #DDDDDD;
- padding: 3px;
- padding-left: 10px;
- }
+ /* Styles overwridden or changed from options.css. */
- #popupMenu a:hover {
- background: #EEEEEE;
+ #footerWrapper {
+ width: 450px; /* As for #endSpace */
+ margin-left: 0px;
}
- #optionsLink {
- font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
- font-size: 12px;
- float: right;
- }
- #helpText {
- color: #979ca0;
- font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
- font-size: 12px;
- float: left;
- display: none;
+ #endSpace {
+ /* Leave space for the fixed footer. */
+ min-height: 36px;
+ max-height: 36px;
}
+
</style>
- <script src="popup.js"></script>
+ <script src="options.js"></script>
</head>
<body>
- <div id="vimiumPopup">
- <div id="excludeControls">
- <input id="popupPattern" placeholder="Pattern against which to match URLs..." type="text" /><br/>
- <input id="popupPassKeys" placeholder="Only exclude these keys..." type="text" /><br/>
- <input id="popupRemove" type="button" value="Remove Rule" />
- <input id="popupExclude" type="button" value="Add or Update Rule" />
- <span id="confirmationMessage">Text is added in popup.coffee.</span>
- </div>
+ <!-- Copied (almost) directly from options.html - start -->
+ <div id="exclusionScrollBox">
+ <table id="exclusionRules">
+ <tr>
+ <td><span class="exclusionHeaderText">URL Patterns</span></td>
+ <td><span class="exclusionHeaderText">Excluded Keys</span></td>
+ </tr>
+ </table>
+ <template id="exclusionRuleTemplate">
+ <tr class="exclusionRuleTemplateInstance">
+ <td><input/ type="text" class="pattern" placeholder="URL pattern"></td>
+ <td class="exclusionRulePassKeys"><input/ type="text" class="passKeys" placeholder="Excluded keys"></td>
+ <td class="exclusionRemoveButton">
+ <input/ type="button" tabindex = "-1" class="exclusionRemoveButtonButton" value="&#x2716;"></td>
+ </tr>
+ </template>
+ </div>
+ <!-- Copied (almost) directly from options.html - end -->
+
+ <!-- Some extra space which is hidden underneath the footer. -->
+ <div id="endSpace"/>
- <div id="popupMenu">
- <ul>
- <li>
- <span id="helpText">Type <strong>Ctrl-Enter</strong> to save and close.</span>
- <a id="optionsLink" target="_blank">Options</a>
- </li>
- </ul>
+ <div id="footer">
+ <div id="footerWrapper">
+ <table id="footerTable">
+ <tr>
+ <td id="footerTableData">
+ <span>
+ <span id="helpText">These are the matching exclusion rules for this page.</span>
+ <br/>
+ <span> <a id="optionsLink" target="_blank">Vimium Options</a>.</span>
+ </span>
+ </td>
+ <td>
+ <button id="exclusionAddButton">Add Rule</button>
+ </td>
+ </tr>
+ </table>
</div>
</div>
</body>