Move marquee to offset by pixels (#170)

In anticipation of supporting the ability to drag the marquee contents, we're
moving to offsetting by pixels rather than actually modifying the text.
This commit is contained in:
Jordan Eldredge 2016-07-28 18:08:51 -07:00 committed by GitHub
parent d34d364a69
commit 0f74f15689
3 changed files with 76 additions and 30 deletions

View file

@ -28,17 +28,22 @@ const getDoubleSizeModeText = (enabled) => {
return `${enabled ? 'Disable' : 'Enable'} doublesize mode`;
};
const wrapForMarquee = (text, step) => {
if (text.length <= 30) {
return text;
const isLong = (text) => text.length > 30;
// Given text and step, how many pixels should it be shifted?
const stepOffset = (text, step) => {
if (!isLong(text)) {
return 0;
}
step = step % (text.length + 1);
const chars = text.split('');
const start = chars.slice(step);
const end = chars.slice(0, step);
return [...start, ' ', ...end].slice(0, 30).join('');
return (step % text.length) * 5;
};
// Format an int as negative pixels
const negativePixels = (pixels) => `-${pixels}px`;
// If text is wider than the marquee, it needs to loop
const loopText = (text) => isLong(text) ? text + text : text;
import CharacterString from './CharacterString.jsx';
class Marquee extends React.Component {
@ -91,10 +96,13 @@ class Marquee extends React.Component {
}
render() {
const text = wrapForMarquee(this.getText(), this.props.display.marqueeStep);
return <CharacterString id='marquee' className='text' onMouseDown={this.handleMouseDown}>
{text}
</CharacterString>;
const text = this.getText();
const offset = stepOffset(text, this.props.display.marqueeStep);
return <div id='marquee' className='text' onMouseDown={this.handleMouseDown}>
<CharacterString style={{marginLeft: negativePixels(offset)}} >
{loopText(text)}
</CharacterString>
</div>;
}
}
@ -104,7 +112,9 @@ export {
getPositionText,
getMediaText,
getDoubleSizeModeText,
wrapForMarquee,
negativePixels,
stepOffset,
loopText,
Marquee
};
export default connect(state => state)(Marquee);

View file

@ -1,3 +1,4 @@
jest.unmock('../Marquee.jsx');
jest.unmock('../utils');
import {
@ -6,7 +7,9 @@ import {
getPositionText,
getMediaText,
getDoubleSizeModeText,
wrapForMarquee
stepOffset,
negativePixels,
loopText
} from '../Marquee.jsx';
describe('getBalanceText', () => {
@ -55,35 +58,62 @@ describe('getMediaText', () => {
});
});
describe('wrapForMarquee', () => {
describe('stepOffset', () => {
const long = 'This is a long string. Longer than 30 characters!';
it('truncates to 30 characters', () => {
const actual = wrapForMarquee(long, 0);
const expected = 'This is a long string. Longer ';
it('starts at 0', () => {
const actual = stepOffset(long, 0);
const expected = 0;
expect(actual).toEqual(expected);
});
it('offsets by the number of steps', () => {
const actual = wrapForMarquee(long, 8);
const expected = 'a long string. Longer than 30 ';
it('first step offsets by one character', () => {
const actual = stepOffset(long, 1);
const expected = 5;
expect(actual).toEqual(expected);
});
it('wraps around when step > text length', () => {
const actual = wrapForMarquee(long, 51);
const expected = 'his is a long string. Longer t';
it('resets to 0 when step === string.length', () => {
const actual = stepOffset(long, long.length);
const expected = 0;
expect(actual).toEqual(expected);
});
it('wraps text when it gets to the end', () => {
const actual = wrapForMarquee(long, 30);
const expected = 'than 30 characters! This is a ';
it('offsets by one char when step = string.length + 1', () => {
const actual = stepOffset(long, long.length + 1);
const expected = 5;
expect(actual).toEqual(expected);
});
it('does not step through short strings', () => {
const actual = wrapForMarquee('Short string', 30);
const expected = 'Short string';
xit('does not try to offset strings shorter than 30 characters', () => {
const actual = stepOffset('hello', 15);
const expected = 0;
expect(actual).toEqual(expected);
});
});
describe('negativePixels', () => {
it('converts an integer into a CSS offset', () => {
const actual = negativePixels(1);
const expected = '-1px';
expect(actual).toEqual(expected);
});
it('handles 0', () => {
const actual = negativePixels(0);
const expected = '-0px';
expect(actual).toEqual(expected);
});
});
describe('loopText', () => {
const long = 'This is a long string. Longer than 30 characters!';
const short = 'This is a short string.';
it('loops long string', () => {
const actual = loopText(long);
const expected = long + long;
expect(actual).toEqual(expected);
});
it('does not loop sort strings', () => {
const actual = loopText(short);
const expected = short;
expect(actual).toEqual(expected);
});
});
describe('getDoubleSizeModeText', () => {
it('prompts to enable when disabled', () => {
const actual = getDoubleSizeModeText(true);

View file

@ -56,5 +56,11 @@
"react-redux": "^4.4.5",
"redux": "^3.5.2",
"redux-thunk": "^2.1.0"
},
"jest": {
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-redux/"
]
}
}