Bug 1174702 - Fix unnecessary scroll on Windows while editing context. r=mikedeboer
authorMark Banner <standard8@mozilla.com>
Thu, 27 Aug 2015 12:10:47 +0100
changeset 292193 9b640a52dca23793d1b16b30ecda9bc4f5b08551
parent 292192 cdc4dc6af44936b6c5b2a188136c06007e57569a
child 292194 0077cc462038eaf7cd0c2c16298b0b58b2f9c061
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1174702
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1174702 - Fix unnecessary scroll on Windows while editing context. r=mikedeboer
browser/components/loop/content/js/roomViews.js
browser/components/loop/content/js/roomViews.jsx
browser/components/loop/content/shared/css/common.css
browser/components/loop/content/shared/css/conversation.css
browser/components/loop/content/shared/js/views.js
browser/components/loop/content/shared/js/views.jsx
browser/components/loop/test/shared/views_test.js
--- a/browser/components/loop/content/js/roomViews.js
+++ b/browser/components/loop/content/js/roomViews.js
@@ -486,16 +486,17 @@ loop.roomViews = (function(mozL10n) {
           ), 
           React.createElement("div", {className: "room-context-label"}, mozL10n.get("context_inroom_label")), 
           React.createElement(sharedViews.Checkbox, {
             additionalClass: cx({ hide: !checkboxLabel }), 
             checked: checked, 
             disabled: checked, 
             label: checkboxLabel, 
             onChange: this.handleCheckboxChange, 
+            useEllipsis: true, 
             value: location}), 
           React.createElement("form", {onSubmit: this.handleFormSubmit}, 
             React.createElement("input", {className: "room-context-name", 
               maxLength: this.maxRoomNameLength, 
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: mozL10n.get("context_edit_name_placeholder"), 
               type: "text", 
               valueLink: this.linkState("newRoomName")}), 
@@ -503,17 +504,17 @@ loop.roomViews = (function(mozL10n) {
               disabled: availableContext && availableContext.url === this.state.newRoomURL, 
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: "https://", 
               type: "text", 
               valueLink: this.linkState("newRoomURL")}), 
             React.createElement("textarea", {className: "room-context-comments", 
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: mozL10n.get("context_edit_comments_placeholder"), 
-              rows: "3", type: "text", 
+              rows: "2", type: "text", 
               valueLink: this.linkState("newRoomDescription")})
           ), 
           React.createElement("button", {className: "btn btn-info", 
                   disabled: this.props.savingContext, 
                   onClick: this.handleFormSubmit}, 
             mozL10n.get("context_save_label2")
           ), 
           React.createElement("button", {className: "room-context-btn-close", 
--- a/browser/components/loop/content/js/roomViews.jsx
+++ b/browser/components/loop/content/js/roomViews.jsx
@@ -486,16 +486,17 @@ loop.roomViews = (function(mozL10n) {
           </p>
           <div className="room-context-label">{mozL10n.get("context_inroom_label")}</div>
           <sharedViews.Checkbox
             additionalClass={cx({ hide: !checkboxLabel })}
             checked={checked}
             disabled={checked}
             label={checkboxLabel}
             onChange={this.handleCheckboxChange}
+            useEllipsis={true}
             value={location} />
           <form onSubmit={this.handleFormSubmit}>
             <input className="room-context-name"
               maxLength={this.maxRoomNameLength}
               onKeyDown={this.handleTextareaKeyDown}
               placeholder={mozL10n.get("context_edit_name_placeholder")}
               type="text"
               valueLink={this.linkState("newRoomName")} />
@@ -503,17 +504,17 @@ loop.roomViews = (function(mozL10n) {
               disabled={availableContext && availableContext.url === this.state.newRoomURL}
               onKeyDown={this.handleTextareaKeyDown}
               placeholder="https://"
               type="text"
               valueLink={this.linkState("newRoomURL")} />
             <textarea className="room-context-comments"
               onKeyDown={this.handleTextareaKeyDown}
               placeholder={mozL10n.get("context_edit_comments_placeholder")}
-              rows="3" type="text"
+              rows="2" type="text"
               valueLink={this.linkState("newRoomDescription")} />
           </form>
           <button className="btn btn-info"
                   disabled={this.props.savingContext}
                   onClick={this.handleFormSubmit}>
             {mozL10n.get("context_save_label2")}
           </button>
           <button className="room-context-btn-close"
--- a/browser/components/loop/content/shared/css/common.css
+++ b/browser/components/loop/content/shared/css/common.css
@@ -519,16 +519,22 @@ html[dir="rtl"] .checkbox {
 .checkbox.disabled {
   border: 1px solid #909090;
 }
 
 .checkbox.checked.disabled {
   background-image: url("../img/check.svg#check-disabled");
 }
 
+.checkbox-label.ellipsis {
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
 /* ContextUrlView classes */
 
 .context-content {
   color: black;
   text-align: left;
 }
 
 html[dir="rtl"] .context-content {
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -944,16 +944,17 @@ body[platform="win"] .share-service-drop
 .room-context > .error-display-area.error {
   margin: 1em 0 .5em 0;
   text-align: center;
   text-shadow: 1px 1px 0 rgba(0,0,0,.3);
 }
 
 .room-context > .checkbox-wrapper {
   margin-bottom: .5em;
+  width: 100%;
 }
 
 .room-context-label {
   margin-bottom: 1em;
 }
 
 .room-context-label,
 .room-context > .checkbox-wrapper > label {
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -852,27 +852,31 @@ loop.shared.views = (function(_, mozL10n
 
   var Checkbox = React.createClass({displayName: "Checkbox",
     propTypes: {
       additionalClass: React.PropTypes.string,
       checked: React.PropTypes.bool,
       disabled: React.PropTypes.bool,
       label: React.PropTypes.string,
       onChange: React.PropTypes.func.isRequired,
+      // If true, this will cause the label to be cut off at the end of the
+      // first line with an ellipsis, and a tooltip supplied.
+      useEllipsis: React.PropTypes.bool,
       // If `value` is not supplied, the consumer should rely on the boolean
       // `checked` state changes.
       value: React.PropTypes.string
     },
 
     getDefaultProps: function() {
       return {
         additionalClass: "",
         checked: false,
         disabled: false,
         label: null,
+        useEllipsis: false,
         value: ""
       };
     },
 
     componentWillReceiveProps: function(nextProps) {
       // Only change the state if the prop has changed, and if it is also
       // different from the state.
       if (this.props.checked !== nextProps.checked &&
@@ -905,27 +909,36 @@ loop.shared.views = (function(_, mozL10n
         "checkbox-wrapper": true,
         disabled: this.props.disabled
       };
       var checkClasses = {
         checkbox: true,
         checked: this.state.checked,
         disabled: this.props.disabled
       };
+      var labelClasses = {
+        "checkbox-label": true,
+        "ellipsis": this.props.useEllipsis
+      };
+
       if (this.props.additionalClass) {
         wrapperClasses[this.props.additionalClass] = true;
       }
       return (
         React.createElement("div", {className: cx(wrapperClasses), 
              disabled: this.props.disabled, 
              onClick: this._handleClick}, 
           React.createElement("div", {className: cx(checkClasses)}), 
-          this.props.label ?
-            React.createElement("label", null, this.props.label) :
-            null
+          
+            this.props.label ?
+              React.createElement("div", {className: cx(labelClasses), 
+                   title: this.props.useEllipsis ? this.props.label : ""}, 
+                this.props.label
+              ) : null
+          
         )
       );
     }
   });
 
   /**
    * Renders an avatar element for display when video is muted.
    */
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -852,27 +852,31 @@ loop.shared.views = (function(_, mozL10n
 
   var Checkbox = React.createClass({
     propTypes: {
       additionalClass: React.PropTypes.string,
       checked: React.PropTypes.bool,
       disabled: React.PropTypes.bool,
       label: React.PropTypes.string,
       onChange: React.PropTypes.func.isRequired,
+      // If true, this will cause the label to be cut off at the end of the
+      // first line with an ellipsis, and a tooltip supplied.
+      useEllipsis: React.PropTypes.bool,
       // If `value` is not supplied, the consumer should rely on the boolean
       // `checked` state changes.
       value: React.PropTypes.string
     },
 
     getDefaultProps: function() {
       return {
         additionalClass: "",
         checked: false,
         disabled: false,
         label: null,
+        useEllipsis: false,
         value: ""
       };
     },
 
     componentWillReceiveProps: function(nextProps) {
       // Only change the state if the prop has changed, and if it is also
       // different from the state.
       if (this.props.checked !== nextProps.checked &&
@@ -905,27 +909,36 @@ loop.shared.views = (function(_, mozL10n
         "checkbox-wrapper": true,
         disabled: this.props.disabled
       };
       var checkClasses = {
         checkbox: true,
         checked: this.state.checked,
         disabled: this.props.disabled
       };
+      var labelClasses = {
+        "checkbox-label": true,
+        "ellipsis": this.props.useEllipsis
+      };
+
       if (this.props.additionalClass) {
         wrapperClasses[this.props.additionalClass] = true;
       }
       return (
         <div className={cx(wrapperClasses)}
              disabled={this.props.disabled}
              onClick={this._handleClick}>
           <div className={cx(checkClasses)} />
-          {this.props.label ?
-            <label>{this.props.label}</label> :
-            null}
+          {
+            this.props.label ?
+              <div className={cx(labelClasses)}
+                   title={this.props.useEllipsis ? this.props.label : ""}>
+                {this.props.label}
+              </div> : null
+          }
         </div>
       );
     }
   });
 
   /**
    * Renders an avatar element for display when video is muted.
    */
--- a/browser/components/loop/test/shared/views_test.js
+++ b/browser/components/loop/test/shared/views_test.js
@@ -936,17 +936,17 @@ describe("loop.shared.views", function()
         expect(node.hasAttribute("disabled")).to.eql(false);
         expect(node.childNodes.length).to.eql(1);
       });
 
       it("should render a label when it's supplied", function() {
         view = mountTestComponent({ label: "Some label" });
 
         var node = view.getDOMNode();
-        expect(node.lastChild.localName).to.eql("label");
+        expect(node.lastChild.localName).to.eql("div");
         expect(node.lastChild.textContent).to.eql("Some label");
       });
 
       it("should render the checkbox as disabled when told to", function() {
         view = mountTestComponent({
           disabled: true
         });
 
@@ -969,16 +969,36 @@ describe("loop.shared.views", function()
           checked: true
         });
 
         view.setProps({checked: false});
 
         var checkbox = view.getDOMNode().querySelector(".checkbox");
         expect(checkbox.classList.contains("checked")).eql(false);
       });
+
+      it("should add an ellipsis class when the prop is set", function() {
+        view = mountTestComponent({
+          label: "Some label",
+          useEllipsis: true
+        });
+
+        var label = view.getDOMNode().querySelector(".checkbox-label");
+        expect(label.classList.contains("ellipsis")).eql(true);
+      });
+
+      it("should not add an ellipsis class when the prop is not set", function() {
+        view = mountTestComponent({
+          label: "Some label",
+          useEllipsis: false
+        });
+
+        var label = view.getDOMNode().querySelector(".checkbox-label");
+        expect(label.classList.contains("ellipsis")).eql(false);
+      });
     });
 
     describe("#_handleClick", function() {
       var onChange;
 
       beforeEach(function() {
         onChange = sinon.stub();
       });