Skip to content

Commit

Permalink
Add url hash params to link to a set of options.
Browse files Browse the repository at this point in the history
Fixes #6.
  • Loading branch information
oliverzheng committed May 31, 2015
1 parent 01a2000 commit 238ad1b
Show file tree
Hide file tree
Showing 16 changed files with 535 additions and 19 deletions.
68 changes: 65 additions & 3 deletions js/app.js
Expand Up @@ -2,11 +2,73 @@

var MainComponent = require('./components/MainComponent');
var React = require('react');

var qs = require('qs');
var attachFastClick = require('fastclick');
var LocationBar = require('location-bar');
var serialization = require('./serialization');
var Options = require('./how/Options');

attachFastClick(document.body);

React.render(
<MainComponent />,
var locationBar = new LocationBar();

function onOptionsChange(
content: Options.Content,
container: Options.Container,
horizontalAlignment: Options.HorizontalAlignment,
verticalAlignment: Options.VerticalAlignment,
browserSupport: Options.BrowserSupport
) {
var serialized = serialization.serializeOptions(
content,
container,
horizontalAlignment,
verticalAlignment,
browserSupport
);
var serializedString = qs.stringify(serialized);
// qs uses brackets[] for sub objects, but that's ugly. It supports parsing
// dot notation, but not generating it. Let's just convert it over, since we
// don't have any real user-inputable data that can contain [] anyway.
var serializedString = serializedString
.replace(/%5B/g, '.')
.replace(/%5D/g, '');
locationBar.update(serializedString);
}

var component = React.render(
<MainComponent
onOptionsChange={onOptionsChange}
/>,
document.getElementById('app')
);

locationBar.onChange((path) => {
var serialized = qs.parse(path);
if (!serialized) {
return;
}

var options = serialization.deserializeOptions(serialized);
if (!options) {
return;
}

var {
content,
container,
horizontalAlignment,
verticalAlignment,
browserSupport,
} = options;

component.setOptions(
content,
container,
horizontalAlignment,
verticalAlignment,
browserSupport
);
});

locationBar.start();
8 changes: 8 additions & 0 deletions js/components/AlignmentComponent.js
Expand Up @@ -14,10 +14,18 @@ class AlignmentComponent extends React.Component {
return this._horizontal.getValue();
}

setHorizontalAlignment(alignment: Options.HorizontalAlignment) {
this._horizontal.select(alignment);
}

getVerticalAlignment(): ?Options.VerticalAlignment {
return this._vertical.getValue();
}

setVerticalAlignment(alignment: Options.VerticalAlignment) {
this._vertical.select(alignment);
}

render(): ?ReactElement {
return (
<div>
Expand Down
23 changes: 23 additions & 0 deletions js/components/BrowserSupportComponent.js
Expand Up @@ -14,6 +14,8 @@ class BrowserSupportComponent extends React.Component {
};
}

_radioList: RadioListComponent;

state: {
browserSupport: Options.BrowserSupport;
};
Expand All @@ -22,6 +24,18 @@ class BrowserSupportComponent extends React.Component {
return this.state.browserSupport;
}

setBrowserSupport(browserSupport: Options.BrowserSupport) {
this.setState({browserSupport});
// Only do IE for now
var browserVersion = browserSupport.browserVersionsRequired[0];
if (browserVersion) {
this._radioList.select({
browser: browserVersion.browser,
version: browserVersion.minVersion,
});
}
}

_handleBrowserSupportChange(
support: { browser: Options.Browser; version: ?string; }
) {
Expand All @@ -31,6 +45,13 @@ class BrowserSupportComponent extends React.Component {
this.setState({browserSupport: this.state.browserSupport});
}

_compareBrowserSupports(
s1: {browser: Options.Browser; version: ?string;},
s2: {browser: Options.Browser; version: ?string;}
): bool {
return s1.browser === s2.browser && s1.version === s2.version;
}

render(): ?ReactElement {
var browser = Options.Browser.IE;
var noSupport = {
Expand All @@ -44,6 +65,8 @@ class BrowserSupportComponent extends React.Component {
What is the minimum version of {browser.name} you need to support?
</p>
<RadioListComponent
ref={(c) => this._radioList = c}
compareValues={this._compareBrowserSupports}
onChange={this._handleBrowserSupportChange.bind(this)}>
<RadioComponent labelText="None" value={noSupport} />
{browser.versions.map(version => {
Expand Down
5 changes: 5 additions & 0 deletions js/components/ContainerComponent.js
Expand Up @@ -15,6 +15,11 @@ class ContainerComponent extends React.Component {
);
}

setContainer(container: Options.Container) {
this._divSize.setWidth(container.width);
this._divSize.setHeight(container.height);
}

render(): ?ReactElement {
return (
<div>
Expand Down
49 changes: 48 additions & 1 deletion js/components/ContentComponent.js
@@ -1,5 +1,7 @@
/** @flow */

var invariant = require('invariant');

var React = require('react');
var LengthComponent = require('./LengthComponent');
var DivSizeComponent = require('./DivSizeComponent');
Expand All @@ -25,6 +27,7 @@ class ContentComponent extends React.Component {
contentType: ?ContentType;
textLines: ?number;
};
_typeRadioList: ?RadioListComponent<ContentType>;
_divSize: ?DivSizeComponent;
_textLines: ?TextLinesComponent;
_textFontSize: ?TextFontSizeComponent;
Expand Down Expand Up @@ -65,6 +68,48 @@ class ContentComponent extends React.Component {
return null;
}

setContent(content: Options.Content) {
var contentText = content.text;

var contentType = contentText ? ContentType.TEXT : ContentType.DIV;
var typeRadioList = this._typeRadioList;
invariant(typeRadioList, 'should have this');
typeRadioList.select(contentType);

if (contentText) {
this.setState({
contentType: contentType,
textLines: contentText.lines,
}, () => {
invariant(contentText, 'flow');

var textLinesComponent = this._textLines;
invariant(textLinesComponent, 'should have text lines component');
textLinesComponent.setLines(contentText.lines);

var fontSizeComponent = this._textFontSize;
if (fontSizeComponent) {
fontSizeComponent.setFontSize(contentText.fontSize);
}

var lineHeightComponent = this._textLineHeight;
if (lineHeightComponent) {
lineHeightComponent.setLineHeight(contentText.lineHeight);
}
});
} else {
this.setState({
contentType: contentType,
}, () => {
var divSizeComponent = this._divSize;
invariant(divSizeComponent, 'should have div size component');

divSizeComponent.setWidth(content.width);
divSizeComponent.setHeight(content.height);
});
}
}

_handleTypeChange(contentType: ContentType) {
this.setState({contentType});
}
Expand Down Expand Up @@ -111,7 +156,9 @@ class ContentComponent extends React.Component {
<div>
<h2>Content</h2>
<p>What do you want to center?</p>
<RadioListComponent onChange={this._handleTypeChange.bind(this)}>
<RadioListComponent
ref={(c) => this._typeRadioList = c}
onChange={this._handleTypeChange.bind(this)}>
<RadioComponent labelText="Text" value={ContentType.TEXT}>
Just text, or an inline-level block of text and images.
</RadioComponent>
Expand Down
28 changes: 26 additions & 2 deletions js/components/DivSizeComponent.js
Expand Up @@ -7,17 +7,37 @@ var RadioComponent = require('./RadioComponent');
var RadioListComponent = require('./RadioListComponent');

class DivSizeComponent extends React.Component {
_widthRadioList: RadioListComponent<bool>;
_heightRadioList: RadioListComponent<bool>;
_width: LengthComponent;
_height: LengthComponent;

getWidth(): ?Options.Length {
return this._width.getLength();
}

setWidth(length: ?Options.Length) {
if (length) {
this._widthRadioList.select(true);
this._width.setLength(length);
} else {
this._widthRadioList.select(false);
}
}

getHeight(): ?Options.Length {
return this._height.getLength();
}

setHeight(length: ?Options.Length) {
if (length) {
this._heightRadioList.select(true);
this._height.setLength(length);
} else {
this._heightRadioList.select(false);
}
}

_handleWidthKnown(known: bool) {
if (!known) {
if (this.props.onWidthChange) {
Expand All @@ -44,7 +64,9 @@ class DivSizeComponent extends React.Component {
return (
<div>
<h3>Width</h3>
<RadioListComponent onChange={this._handleWidthKnown.bind(this)}>
<RadioListComponent
ref={(c) => this._widthRadioList = c}
onChange={this._handleWidthKnown.bind(this)}>
<RadioComponent labelText="Known" value={true}>
<LengthComponent
onChange={this.props.onWidthChange}
Expand All @@ -57,7 +79,9 @@ class DivSizeComponent extends React.Component {
</RadioListComponent>

<h3>Height</h3>
<RadioListComponent onChange={this._handleHeightKnown.bind(this)}>
<RadioListComponent
ref={(c) => this._heightRadioList = c}
onChange={this._handleHeightKnown.bind(this)}>
<RadioComponent labelText="Known" value={true}>
<LengthComponent
onChange={this.props.onHeightChange}
Expand Down
8 changes: 8 additions & 0 deletions js/components/LengthComponent.js
Expand Up @@ -25,6 +25,14 @@ class LengthComponent extends React.Component {
return new Options.Length(this.state.value, this.state.type);
}

setLength(length: Options.Length) {
this.setState({
value: length.value,
type: length.lengthType,
});
this._radioList.select(length.lengthType);
}

selectDefaultType() {
this._radioList.select(Options.LengthType.PIXEL);
}
Expand Down
31 changes: 31 additions & 0 deletions js/components/MainComponent.js
Expand Up @@ -4,6 +4,7 @@ var React = require('react');
var OptionsComponent = require('./OptionsComponent');
var CodeComponent = require('./CodeComponent');

var Options = require('../how/Options');
var findMethod = require('../how/findMethod');

class MainComponent extends React.Component {
Expand Down Expand Up @@ -35,6 +36,32 @@ class MainComponent extends React.Component {
} else {
this._code.setNoMethod();
}

if (this.props.onOptionsChange) {
this.props.onOptionsChange(
content,
container,
horizontalAlignment,
verticalAlignment,
browserSupport
);
}
}

setOptions(
content: Options.Content,
container: Options.Container,
horizontalAlignment: Options.HorizontalAlignment,
verticalAlignment: Options.VerticalAlignment,
browserSupport: Options.BrowserSupport
) {
this._options.setOptions(
content,
container,
horizontalAlignment,
verticalAlignment,
browserSupport
);
}

render(): ?ReactElement {
Expand Down Expand Up @@ -80,4 +107,8 @@ class MainComponent extends React.Component {
}
}

MainComponent.propTypes = {
onOptionsChange: React.PropTypes.func,
};

module.exports = MainComponent;
15 changes: 14 additions & 1 deletion js/components/OptionsComponent.js
Expand Up @@ -46,8 +46,21 @@ class OptionsComponent extends React.Component {
return this._browserSupport.getBrowserSupport();
}

setOptions(
content: Options.Content,
container: Options.Container,
horizontalAlignment: Options.HorizontalAlignment,
verticalAlignment: Options.VerticalAlignment,
browserSupport: Options.BrowserSupport
) {
this._content.setContent(content);
this._container.setContainer(container);
this._alignment.setHorizontalAlignment(horizontalAlignment);
this._alignment.setVerticalAlignment(verticalAlignment);
this._browserSupport.setBrowserSupport(browserSupport);
}

render(): ?ReactElement {
// TODO add browser support back in when we need it.
return (
<div>
<ContentComponent ref={(c) => this._content = c} />
Expand Down

0 comments on commit 238ad1b

Please sign in to comment.