PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/scripts/main.jsx

https://gitlab.com/andyblaesus/wy-index
JSX | 556 lines | 436 code | 90 blank | 30 comment | 14 complexity | b593291623de3a493a24f38b1d70b6af MD5 | raw file
  1. xdomain.slaves({
  2. "http://s.init.im:8081": "/proxy.html"
  3. });
  4. window.React = require('react');
  5. wyQuiz.setNewUUID = function() {
  6. // If localStorage contains an existing UUID, use it as the UUID of the app.
  7. // Otherwise, get a UUID from server.
  8. "use strict";
  9. if (localStorage.getItem('uuid')) {
  10. this.uuid = localStorage.getItem('uuid');
  11. } else {
  12. var url = 'http://s.init.im:8081/utility/uuid/';
  13. var uuid = 'DEFAULT'+Math.random().toString(); // In case UUID server fails
  14. this.uuid = uuid;
  15. localStorage.setItem('uuid', uuid);
  16. var request = new XMLHttpRequest();
  17. request.open('GET', url, true);
  18. request.onload = function () {
  19. console.log('UUID server responded');
  20. if (request.status >= 200 && request.status < 400) {
  21. var response = JSON.parse(request.responseText);
  22. if (response.success) {
  23. uuid = response.data.uuid;
  24. }
  25. }
  26. this.uuid = uuid;
  27. localStorage.setItem('uuid', uuid);
  28. }.bind(this);
  29. request.send();
  30. }
  31. };
  32. function post(keyToPost, valueToPost) {
  33. "use strict";
  34. var url = "http://s.init.im:8081/remember/wyIndexQuiz/";
  35. var request = new XMLHttpRequest();
  36. var message = {
  37. username: wyQuiz.uuid,
  38. key: keyToPost,
  39. value: valueToPost,
  40. raw: '',
  41. datetime: Date.now()
  42. };
  43. request.open('POST', url, true);
  44. request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
  45. var jsonString = JSON.stringify(message);
  46. request.send(jsonString);
  47. console.log('Tried to post '+jsonString);
  48. }
  49. function extend(object1, object2) {
  50. // Parameters are not modified
  51. var result = {},
  52. prop;
  53. for (prop in object1) if (object1.hasOwnProperty(prop)) {
  54. result[prop] = object1[prop];
  55. }
  56. for (prop in object2) if (object2.hasOwnProperty(prop)) {
  57. result[prop] = object2[prop];
  58. }
  59. return result;
  60. }
  61. var themeColor = "#2AB6C9";
  62. var baseStyle = {
  63. backgroundColor: themeColor,
  64. fontFamily: '"Hiragino Sans GB", sans-serif',
  65. maxWidth: '1125px',
  66. margin: '0 auto',
  67. color: '#EEE',
  68. fontSize: '2em',
  69. padding: '1em'
  70. };
  71. // Style for narrow screens
  72. var width = window.innerWidth
  73. || document.documentElement.clientWidth
  74. || document.body.clientWidth;
  75. if (width < 1125) {
  76. baseStyle.fontSize = '2.2em';
  77. }
  78. // Narrow screen style ends
  79. var ResultCard = React.createClass({
  80. shareToWeibo: function () {
  81. var title = encodeURIComponent(wyQuiz.shareRecommendation),
  82. url = encodeURIComponent(wyQuiz.url);
  83. window.open('http://v.t.sina.com.cn/share/share.php?title='+title+'&url='+url);
  84. post('share', 'weibo');
  85. },
  86. shareToFacebook: function () {
  87. var description = encodeURIComponent(wyQuiz.shareRecommendation),
  88. url = encodeURIComponent(wyQuiz.url),
  89. title = encodeURIComponent(wyQuiz.title),
  90. imageURL = encodeURIComponent(wyQuiz.url + './images/cover-share.png');
  91. window.open('https://www.facebook.com/dialog/feed?app_id=871017952984021' +
  92. '&link=' + url +
  93. '&picture=' + imageURL +
  94. '&name=' + title +
  95. '&description=' + description +
  96. '&redirect_uri=' + url
  97. );
  98. post('share', 'facebook');
  99. },
  100. shareToTwitter: function() {
  101. var title=encodeURIComponent(wyQuiz.shareRecommendation),
  102. url=encodeURIComponent(wyQuiz.url);
  103. window.open('https://twitter.com/share?url=' +
  104. url +
  105. '&text=' +
  106. title);
  107. },
  108. render: function() {
  109. var cardStyle = {
  110. };
  111. cardStyle = extend(baseStyle, cardStyle);
  112. var commentTitleStyle = {
  113. fontSize: "1.4em"
  114. };
  115. var indexMessageStyle = {
  116. fontSize: "1.4em"
  117. };
  118. var imageBoxLeftStyle = {
  119. textAlign: "center",
  120. display: "inline-block",
  121. float: "left",
  122. width: "10%",
  123. };
  124. var humanFigureImageStyle = {
  125. width: '100%'
  126. };
  127. var imageBoxRightStyle = {
  128. textAlign: "center",
  129. display: "inline-block",
  130. float: "right",
  131. width: "10%",
  132. };
  133. var indexBoxStyle = {
  134. display: "inline-block",
  135. width: "100%",
  136. position: "relative"
  137. };
  138. var dataBoxStyle = {
  139. width: "70%",
  140. position: "absolute",
  141. bottom: 0,
  142. margin: "0 15%",
  143. textAlign: "center",
  144. fontSize: "3em"
  145. };
  146. var gradientStyle = {
  147. width: "100%",
  148. marginBottom: "-0.3em",
  149. };
  150. var scoreMarginPercentage = this.props.totalScore * 0.97;
  151. var sliderBoxStyle = {
  152. textAlign: "left",
  153. fontSize: "0.5em",
  154. marginLeft: scoreMarginPercentage + "%",
  155. position: "absolute",
  156. bottom: "30px"
  157. };
  158. var socialShareAnchorStyle = {
  159. display: "block",
  160. fontSize: "0.8em",
  161. fontWeight: "bolder",
  162. width: '10em',
  163. textAlign: "left",
  164. marginTop: "0.5em",
  165. verticalAlign: "bottom",
  166. padding: "0",
  167. cursor: "pointer",
  168. border: "4px solid #EEE"
  169. };
  170. var facebookShareAnchorStyle = extend(socialShareAnchorStyle, {});
  171. var weiboShareAnchorStyle = extend(socialShareAnchorStyle, {});
  172. var twitterShareAnchorStyle = extend(socialShareAnchorStyle, {});
  173. return (
  174. <div id="ResultCard"
  175. style={cardStyle}>
  176. <div id="indexMessage"
  177. style={indexMessageStyle}>
  178. {this.props.indexMessage}
  179. </div>
  180. <div id="indexBox"
  181. style={indexBoxStyle}>
  182. <div id="imageBoxLeft"
  183. style={imageBoxLeftStyle}>
  184. <img src="./images/resultpage_image_left.png" style={humanFigureImageStyle} />
  185. <div id="indexLowerBound">
  186. 0
  187. </div>
  188. </div>
  189. <div id="imageBoxRight"
  190. style={imageBoxRightStyle}>
  191. <img src="./images/resultpage_image_right.png" style={humanFigureImageStyle}/>
  192. <div id="indexUpperBound">
  193. 100
  194. </div>
  195. </div>
  196. <div id="dataBox"
  197. style={dataBoxStyle}>
  198. {this.props.totalScore}
  199. <div id="sliderBox"
  200. style={sliderBoxStyle}>
  201. </div>
  202. <img src="./images/gradient.png"
  203. id="gradient"
  204. style={gradientStyle}/>
  205. </div>
  206. </div>
  207. <div id="commentBox">
  208. <div id="commentTitle"
  209. style={commentTitleStyle}>
  210. {this.props.commentTitle.replace('[totalScore]', this.props.totalScore.toString())}
  211. </div>
  212. <div id="commentContent">
  213. {this.props.commentContent.replace('[totalScore]', this.props.totalScore.toString())}
  214. </div>
  215. </div>
  216. <div id="socialShare">
  217. <a className="btnShare"
  218. id="btnFacebookShare"
  219. style={facebookShareAnchorStyle}
  220. onClick={this.shareToFacebook}>
  221. <img src="./images/facebook_icon.png" alt="" />
  222. 分享到Facebook
  223. </a>
  224. <a className="btnShare"
  225. id="btnWeiboShare"
  226. style={weiboShareAnchorStyle}
  227. onClick={this.shareToWeibo}>
  228. <img src="./images/weibo_icon.png" alt="" />
  229. 分享到新浪微博
  230. </a>
  231. <a className="btnShare"
  232. id="btnTwitterShare"
  233. style={twitterShareAnchorStyle}
  234. onClick={this.shareToTwitter}>
  235. <img src="./images/twitter_icon.png" alt="" />
  236. 分享到Twitter
  237. </a>
  238. </div>
  239. </div>
  240. );
  241. }
  242. });
  243. var QuestionCard = React.createClass({
  244. getInitialState: function() {
  245. return {
  246. questionSerial: this.props.questionSerial,
  247. totalScore: 0
  248. }
  249. },
  250. handleOptionClick: function(event) {
  251. post(this.state.questionSerial.toString(), event.target.innerText);
  252. if (this.state.questionSerial < this.props.survey.length - 1) {
  253. this.setState({
  254. questionSerial: this.state.questionSerial + 1,
  255. totalScore: this.state.totalScore + parseInt(event.target.getAttribute("data-score"), 10)
  256. });
  257. } else {
  258. // Last Question
  259. this.setState({
  260. totalScore: this.state.totalScore + event.target.getAttribute("data-score")
  261. });
  262. var normalisedScore = Math.round(this.state.totalScore / wyQuiz.maximumScore * 100);
  263. post('rawScore', this.state.totalScore.toString());
  264. post('normalisedScore', normalisedScore.toString());
  265. React.render(
  266. <ResultCard totalScore={normalisedScore}
  267. commentTitle={wyQuiz.commentTitle}
  268. commentContent={wyQuiz.commentContent}
  269. indexMessage={wyQuiz.indexMessage} />,
  270. document.getElementById('content')
  271. )
  272. }
  273. },
  274. render: function() {
  275. var question = this.props.survey[this.state.questionSerial];
  276. // === Styles ===
  277. var cardStyle = {
  278. position: "relative"
  279. };
  280. cardStyle = extend(baseStyle, cardStyle);
  281. var listItemStyle = {
  282. marginTop: "0.5em",
  283. cursor: "pointer",
  284. maxWidth: "10em"
  285. };
  286. var imageStyle = {
  287. position: "absolute",
  288. bottom: 0,
  289. right: 0,
  290. maxHeight: "8em"
  291. };
  292. var progressBarBoxStyle = {
  293. position: "relative",
  294. overflow: "hidden",
  295. whiteSpace: "nowrap"
  296. };
  297. var progressBarStyle = {
  298. border: "2px solid white",
  299. height: "1em",
  300. display: 'inline-block',
  301. width: '92%',
  302. textAlign: "center"
  303. };
  304. var questionTextStyle = {
  305. fontSize: "1.5em"
  306. };
  307. var optionBoxStyle = {
  308. overflow: "hidden",
  309. position: "relative"
  310. };
  311. var progressPercentage = (this.state.questionSerial / this.props.survey.length);
  312. var finishedBarStyle = {
  313. position: "relative",
  314. height: "1em",
  315. backgroundColor: "#EEE",
  316. width: (5 + (95 - 5) * progressPercentage).toString() + '%'
  317. };
  318. var finishedQuestionCountStyle = {
  319. float: "right",
  320. position: "relative",
  321. bottom: "0.2em",
  322. paddingRight: "0.1em",
  323. color: themeColor
  324. };
  325. var totalQuestionCountStyle = {
  326. width: "1.5em",
  327. position: "absolute",
  328. rigth: "0",
  329. bottom: "0.2em",
  330. };
  331. // === End of Styles ===
  332. // Generate list items
  333. var optionListItems = question.options.map(function(option){
  334. return (
  335. <li key={option.optionScore + option.optionText}
  336. onClick={this.handleOptionClick}
  337. data-score={option.optionScore}
  338. style={listItemStyle}
  339. >
  340. {option.optionText}
  341. </li>
  342. );
  343. }, this);
  344. return (
  345. <div id="QuestionCard" style={cardStyle}>
  346. <div id="QuestionText"
  347. style={questionTextStyle}
  348. >
  349. {question.questionText}
  350. </div>
  351. <div id="OptionBox"
  352. style={optionBoxStyle}>
  353. <ul id="OptionList">
  354. {optionListItems}
  355. </ul>
  356. {question.imagePath ?
  357. <img id="OptionImage"
  358. src={question.imagePath}
  359. style={imageStyle}
  360. /> :
  361. <div></div>
  362. }
  363. </div>
  364. <div id="ProgressBarBox"
  365. style={progressBarBoxStyle}>
  366. <div id="ProgressBar"
  367. style={progressBarStyle}>
  368. <div id="divFinishedBar"
  369. style={finishedBarStyle}>
  370. <div id="spanFinishedQuestionCount"
  371. style={finishedQuestionCountStyle}>
  372. {this.state.questionSerial}
  373. </div>
  374. </div>
  375. </div>
  376. <span id="spanTotalQuestionCount"
  377. style={totalQuestionCountStyle}>
  378. {this.props.survey.length}
  379. </span>
  380. </div>
  381. </div>
  382. );
  383. }
  384. });
  385. var CoverCard = React.createClass({
  386. handleStartClick: function(event) {
  387. post('start', 'Start button clicked');
  388. React.render(
  389. <QuestionCard
  390. survey={wyQuiz.survey}
  391. questionSerial={0}
  392. />,
  393. document.getElementById('content')
  394. )
  395. },
  396. render: function() {
  397. var cardStyle = {
  398. };
  399. cardStyle = extend(baseStyle, cardStyle);
  400. var textBoxStyle = {
  401. };
  402. var imageStyle = {
  403. display: 'inline-block',
  404. float: 'left',
  405. };
  406. var titleStyle = {
  407. fontSize: '3em',
  408. paddingTop: '1em'
  409. };
  410. var startTextStyle = {
  411. fontColor: 'inherit',
  412. fontSize: '1.5em',
  413. textDecoration: 'none',
  414. marginLeft: '12em',
  415. cursor: 'pointer',
  416. };
  417. return (
  418. <div style={cardStyle}>
  419. <img src={this.props.coverImagePath} style={imageStyle} />
  420. <div id='textBox' style={textBoxStyle}>
  421. <h1 style={titleStyle}>{this.props.title}</h1>
  422. <span
  423. style={startTextStyle}
  424. onClick={this.handleStartClick}>
  425. {this.props.startText + "▶"}
  426. </span>
  427. </div>
  428. </div>
  429. )
  430. }
  431. });
  432. (function(window, document, React, wyQuiz){
  433. document.title = wyQuiz.title;
  434. wyQuiz.setNewUUID();
  435. React.render(
  436. <CoverCard
  437. title={wyQuiz.title}
  438. startText={wyQuiz.startText}
  439. coverImagePath={wyQuiz.coverImgRelativePath}
  440. />,
  441. //<QuestionCard survey={wyQuiz.survey} questionSerial={0} />,
  442. //<ResultCard indexMessage={wyQuiz.indexMessage}
  443. // commentTitle={wyQuiz.commentTitle}
  444. // commentContent={wyQuiz.commentContent}
  445. // totalScore={29} />,
  446. document.getElementById('content')
  447. );
  448. post('render', wyQuiz.lang+'-rendered');
  449. // Add og tags
  450. // Moved to static index.html
  451. //var head = document.head;
  452. //var meta, info;
  453. //var ogInfo = {
  454. // 'og:title': wyQuiz.title,
  455. // 'og:type' : 'article',
  456. // 'og:image': wyQuiz.url + './images/cover-share.png'
  457. //};
  458. //
  459. //for (attr in ogInfo) if (ogInfo.hasOwnProperty(attr)) {
  460. // meta = document.createElement('meta');
  461. // meta.setAttribute('property', attr);
  462. // meta.setAttribute('content', ogInfo[attr]);
  463. // head.appendChild(meta);
  464. //};
  465. }(window, window.document, window.React, window.wyQuiz));