helper.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /**
  19. * Remove spaces at beginning and ending of line.
  20. * @example
  21. * var str = " I'm a string "
  22. * str.trim() // return "I'm a string"
  23. * @method trim
  24. * @return {string}
  25. */
  26. String.prototype.trim = function () {
  27. return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  28. };
  29. /**
  30. * Determines whether string end within another string.
  31. *
  32. * @method endsWith
  33. * @param suffix {string} substring for search
  34. * @return {boolean}
  35. */
  36. String.prototype.endsWith = function(suffix) {
  37. return this.indexOf(suffix, this.length - suffix.length) !== -1;
  38. };
  39. /**
  40. * Determines whether string start within another string.
  41. *
  42. * @method startsWith
  43. * @param prefix {string} substring for search
  44. * @return {boolean}
  45. */
  46. String.prototype.startsWith = function (prefix){
  47. return this.indexOf(prefix) == 0;
  48. };
  49. /**
  50. * Determines whether string founded within another string.
  51. *
  52. * @method contains
  53. * @param substring {string} substring for search
  54. * @return {boolean}
  55. */
  56. String.prototype.contains = function(substring) {
  57. return this.indexOf(substring) != -1;
  58. };
  59. /**
  60. * Capitalize the first letter of string.
  61. * @method capitalize
  62. * @return {string}
  63. */
  64. String.prototype.capitalize = function () {
  65. return this.charAt(0).toUpperCase() + this.slice(1);
  66. };
  67. /**
  68. * Finds the value in an object where this string is a key.
  69. * Optionally, the index of the key can be provided where the
  70. * value of the nth key in the hierarchy is returned.
  71. *
  72. * Example:
  73. * var tofind = 'smart';
  74. * var person = {'name': 'Bob Bob', 'smart': 'no', 'age': '28', 'personality': {'smart': 'yes', 'funny': 'yes', 'emotion': 'happy'} };
  75. * tofind.findIn(person); // 'no'
  76. * tofind.findIn(person, 0); // 'no'
  77. * tofind.findIn(person, 1); // 'yes'
  78. * tofind.findIn(person, 2); // null
  79. *
  80. * @method findIn
  81. * @param multi {object}
  82. * @param index {number} Occurrence count of this key
  83. * @return {*} Value of key at given index
  84. */
  85. String.prototype.findIn = function(multi, index, _foundValues) {
  86. if (!index) {
  87. index = 0;
  88. }
  89. if (!_foundValues) {
  90. _foundValues = [];
  91. }
  92. multi = multi || '';
  93. var value = null;
  94. var str = this.valueOf();
  95. if (typeof multi == 'object') {
  96. for ( var key in multi) {
  97. if (value != null) {
  98. break;
  99. }
  100. if (key == str) {
  101. _foundValues.push(multi[key]);
  102. }
  103. if (_foundValues.length - 1 == index) {
  104. // Found the value
  105. return _foundValues[index];
  106. }
  107. if (typeof multi[key] == 'object') {
  108. value = value || this.findIn(multi[key], index, _foundValues);
  109. }
  110. }
  111. }
  112. return value;
  113. };
  114. /**
  115. * Replace {i} with argument. where i is number of argument to replace with.
  116. * @example
  117. * var str = "{0} world{1}";
  118. * str.format("Hello", "!") // return "Hello world!"
  119. *
  120. * @method format
  121. * @return {string}
  122. */
  123. String.prototype.format = function () {
  124. var args = arguments;
  125. return this.replace(/{(\d+)}/g, function (match, number) {
  126. return typeof args[number] != 'undefined' ? args[number] : match;
  127. });
  128. };
  129. /**
  130. * Wrap words in string within template.
  131. *
  132. * @method highlight
  133. * @param {string[]} words - words to wrap
  134. * @param {string} [highlightTemplate="<b>{0}</b>"] - template for wrapping
  135. * @return {string}
  136. */
  137. String.prototype.highlight = function (words, highlightTemplate) {
  138. var self = this;
  139. highlightTemplate = highlightTemplate ? highlightTemplate : "<b>{0}</b>";
  140. words.forEach(function (word) {
  141. var searchRegExp = new RegExp("\\b" + word + "\\b", "gi");
  142. self = self.replace(searchRegExp, function (found) {
  143. return highlightTemplate.format(found);
  144. });
  145. });
  146. return self;
  147. };
  148. /**
  149. * Convert time in milliseconds to object contained days, hours and minutes.
  150. * @typedef ConvertedTime
  151. * @type {Object}
  152. * @property {number} d - days
  153. * @property {number} h - hours
  154. * @property {string} m - minutes
  155. * @example
  156. * var time = 1000000000;
  157. * time.toDaysHoursMinutes() // {d: 11, h: 13, m: "46.67"}
  158. *
  159. * @method toDaysHoursMinutes
  160. * @return {object}
  161. */
  162. Number.prototype.toDaysHoursMinutes = function () {
  163. var formatted = {},
  164. dateDiff = this,
  165. secK = 1000, //ms
  166. minK = 60 * secK, // sec
  167. hourK = 60 * minK, // sec
  168. dayK = 24 * hourK;
  169. dateDiff = parseInt(dateDiff);
  170. formatted.d = Math.floor(dateDiff / dayK);
  171. dateDiff -= formatted.d * dayK;
  172. formatted.h = Math.floor(dateDiff / hourK);
  173. dateDiff -= formatted.h * hourK;
  174. formatted.m = (dateDiff / minK).toFixed(2);
  175. return formatted;
  176. };
  177. /**
  178. Sort an array by the key specified in the argument.
  179. Handle only native js objects as element of array, not the Ember's object.
  180. Can be used as alternative to sortProperty method of Ember library
  181. in order to speed up executing on large data volumes
  182. @method sortBy
  183. @param {String} path name(s) to sort on
  184. @return {Array} The sorted array.
  185. */
  186. Array.prototype.sortPropertyLight = function (path) {
  187. var realPath = (typeof path === "string") ? path.split('.') : [];
  188. this.sort(function (a, b) {
  189. var aProperty = a;
  190. var bProperty = b;
  191. realPath.forEach(function (key) {
  192. aProperty = aProperty[key];
  193. bProperty = bProperty[key];
  194. });
  195. if (aProperty > bProperty) return 1;
  196. if (aProperty < bProperty) return -1;
  197. return 0;
  198. });
  199. return this;
  200. };
  201. /** @namespace Em **/
  202. Em.CoreObject.reopen({
  203. t:function (key, attrs) {
  204. return Em.I18n.t(key, attrs)
  205. }
  206. });
  207. /** @namespace Em.Handlebars **/
  208. Em.Handlebars.registerHelper('log', function (variable) {
  209. console.log(variable);
  210. });
  211. Em.Handlebars.registerHelper('warn', function (variable) {
  212. console.warn(variable);
  213. });
  214. Em.Handlebars.registerHelper('highlight', function (property, words, fn) {
  215. var context = (fn.contexts && fn.contexts[0]) || this;
  216. property = Em.Handlebars.getPath(context, property, fn);
  217. words = words.split(";");
  218. // if (highlightTemplate == undefined) {
  219. var highlightTemplate = "<b>{0}</b>";
  220. // }
  221. words.forEach(function (word) {
  222. var searchRegExp = new RegExp("\\b" + word + "\\b", "gi");
  223. property = property.replace(searchRegExp, function (found) {
  224. return highlightTemplate.format(found);
  225. });
  226. });
  227. return new Em.Handlebars.SafeString(property);
  228. });
  229. /**
  230. * @namespace App
  231. */
  232. App = require('app');
  233. /**
  234. * Certain variables can have JSON in string
  235. * format, or in JSON format itself.
  236. *
  237. * @memberof App
  238. * @function parseJson
  239. * @param {string|object}
  240. * @return {object}
  241. */
  242. App.parseJSON = function (value) {
  243. if (typeof value == "string") {
  244. return jQuery.parseJSON(value);
  245. }
  246. return value;
  247. };
  248. /**
  249. * Check for empty <code>Object</code>, built in Em.isEmpty()
  250. * doesn't support <code>Object</code> type
  251. *
  252. * @memberof App
  253. * @method isEmptyObject
  254. * @param obj {Object}
  255. * @return {Boolean}
  256. */
  257. App.isEmptyObject = function(obj) {
  258. var empty = true;
  259. for (var prop in obj) { if (obj.hasOwnProperty(prop)) {empty = false; break;} }
  260. return empty;
  261. }
  262. /**
  263. * Returns object with defined keys only.
  264. *
  265. * @memberof App
  266. * @method permit
  267. * @param {Object} obj - input object
  268. * @param {String|Array} keys - allowed keys
  269. * @return {Object}
  270. */
  271. App.permit = function(obj, keys) {
  272. var result = {};
  273. if (typeof obj !== 'object' || App.isEmptyObject(obj)) return result;
  274. if (typeof keys == 'string') keys = Array(keys);
  275. keys.forEach(function(key) {
  276. if (obj.hasOwnProperty(key))
  277. result[key] = obj[key];
  278. });
  279. return result;
  280. };
  281. /**
  282. *
  283. * @namespace App
  284. * @namespace App.format
  285. */
  286. App.format = {
  287. /**
  288. * @memberof App.format
  289. * @type {object}
  290. * @property components
  291. */
  292. components: {
  293. 'APP_TIMELINE_SERVER': 'App Timeline Server',
  294. 'DATANODE': 'DataNode',
  295. 'DECOMMISSION_DATANODE': 'Update Exclude File',
  296. 'DRPC_SERVER': 'DRPC Server',
  297. 'FALCON': 'Falcon',
  298. 'FALCON_CLIENT': 'Falcon Client',
  299. 'FALCON_SERVER': 'Falcon Server',
  300. 'FALCON_SERVICE_CHECK': 'Falcon Service Check',
  301. 'FLUME_HANDLER': 'Flume Agent',
  302. 'FLUME_SERVICE_CHECK': 'Flume Service Check',
  303. 'GANGLIA_MONITOR': 'Ganglia Monitor',
  304. 'GANGLIA_SERVER': 'Ganglia Server',
  305. 'GLUSTERFS_CLIENT': 'GLUSTERFS Client',
  306. 'GLUSTERFS_SERVICE_CHECK': 'GLUSTERFS Service Check',
  307. 'GMETAD_SERVICE_CHECK': 'Gmetad Service Check',
  308. 'GMOND_SERVICE_CHECK': 'Gmond Service Check',
  309. 'HADOOP_CLIENT': 'Hadoop Client',
  310. 'HBASE_CLIENT': 'HBase Client',
  311. 'HBASE_MASTER': 'HBase Master',
  312. 'HBASE_REGIONSERVER': 'RegionServer',
  313. 'HBASE_SERVICE_CHECK': 'HBase Service Check',
  314. 'HCAT': 'HCat',
  315. 'HCAT_SERVICE_CHECK': 'HCat Service Check',
  316. 'HDFS_CLIENT': 'HDFS Client',
  317. 'HDFS_SERVICE_CHECK': 'HDFS Service Check',
  318. 'HISTORYSERVER': 'History Server',
  319. 'HIVE_CLIENT': 'Hive Client',
  320. 'HIVE_METASTORE': 'Hive Metastore',
  321. 'HIVE_SERVER': 'HiveServer2',
  322. 'HIVE_SERVICE_CHECK': 'Hive Service Check',
  323. 'HUE_SERVER': 'Hue Server',
  324. 'JAVA_JCE': 'Java JCE',
  325. 'JOBTRACKER': 'JobTracker',
  326. 'JOBTRACKER_SERVICE_CHECK': 'JobTracker Service Check',
  327. 'JOURNALNODE': 'JournalNode',
  328. 'KERBEROS_ADMIN_CLIENT': 'Kerberos Admin Client',
  329. 'KERBEROS_CLIENT': 'Kerberos Client',
  330. 'KERBEROS_SERVER': 'Kerberos Server',
  331. 'MAPREDUCE2_CLIENT': 'MapReduce2 Client',
  332. 'MAPREDUCE2_SERVICE_CHECK': 'MapReduce2 Service Check',
  333. 'MAPREDUCE_CLIENT': 'MapReduce Client',
  334. 'MAPREDUCE_SERVICE_CHECK': 'MapReduce Service Check',
  335. 'MYSQL_SERVER': 'MySQL Server',
  336. 'NAGIOS_SERVER': 'Nagios Server',
  337. 'NAMENODE': 'NameNode',
  338. 'NAMENODE_SERVICE_CHECK': 'NameNode Service Check',
  339. 'NIMBUS': 'Nimbus',
  340. 'NODEMANAGER': 'NodeManager',
  341. 'OOZIE_CLIENT': 'Oozie Client',
  342. 'OOZIE_SERVER': 'Oozie Server',
  343. 'OOZIE_SERVICE_CHECK': 'Oozie Service Check',
  344. 'PIG': 'Pig',
  345. 'PIG_SERVICE_CHECK': 'Pig Service Check',
  346. 'RESOURCEMANAGER': 'ResourceManager',
  347. 'SECONDARY_NAMENODE': 'SNameNode',
  348. 'SQOOP': 'Sqoop',
  349. 'SQOOP_SERVICE_CHECK': 'Sqoop Service Check',
  350. 'STORM_REST_API': 'Storm REST API Server',
  351. 'STORM_SERVICE_CHECK': 'Storm Service Check',
  352. 'STORM_UI_SERVER': 'Storm UI Server',
  353. 'SUPERVISOR': 'Supervisor',
  354. 'TASKTRACKER': 'TaskTracker',
  355. 'TEZ_CLIENT': 'Tez Client',
  356. 'WEBHCAT_SERVER': 'WebHCat Server',
  357. 'WEBHCAT_SERVICE_CHECK': 'WebHCat Service Check',
  358. 'YARN_CLIENT': 'YARN Client',
  359. 'YARN_SERVICE_CHECK': 'YARN Service Check',
  360. 'ZKFC': 'ZKFailoverController',
  361. 'ZOOKEEPER_CLIENT': 'ZooKeeper Client',
  362. 'ZOOKEEPER_QUORUM_SERVICE_CHECK': 'ZK Quorum Service Check',
  363. 'ZOOKEEPER_SERVER': 'ZooKeeper Server',
  364. 'ZOOKEEPER_SERVICE_CHECK': 'ZooKeeper Service Check',
  365. 'CLIENT': 'Client'
  366. },
  367. /**
  368. * @memberof App.format
  369. * @property command
  370. * @type {object}
  371. */
  372. command: {
  373. 'INSTALL': 'Install',
  374. 'UNINSTALL': 'Uninstall',
  375. 'START': 'Start',
  376. 'STOP': 'Stop',
  377. 'EXECUTE': 'Execute',
  378. 'ABORT': 'Abort',
  379. 'UPGRADE': 'Upgrade',
  380. 'RESTART': 'Restart',
  381. 'SERVICE_CHECK': 'Check',
  382. 'Excluded:': 'Decommission:',
  383. 'Included:': 'Recommission:'
  384. },
  385. /**
  386. * convert role to readable string
  387. *
  388. * @memberof App.format
  389. * @method role
  390. * @param {string} role
  391. * return {string}
  392. */
  393. role:function (role) {
  394. return this.components[role] ? this.components[role] : '';
  395. },
  396. /**
  397. * convert command_detail to readable string, show the string for all tasks name
  398. *
  399. * @memberof App.format
  400. * @method commandDetail
  401. * @param {string} command_detail
  402. * @return {string}
  403. */
  404. commandDetail: function (command_detail) {
  405. var detailArr = command_detail.split(' ');
  406. var self = this;
  407. var result = '';
  408. detailArr.forEach( function(item) {
  409. // if the item has the pattern SERVICE/COMPONENT, drop the SERVICE part
  410. if (item.contains('/')) {
  411. item = item.split('/')[1];
  412. }
  413. // ignore 'DECOMMISSION', command came from 'excluded/included'
  414. if (item == 'DECOMMISSION,') {
  415. item = '';
  416. }
  417. if (self.components[item]) {
  418. result = result + ' ' + self.components[item];
  419. } else if (self.command[item]) {
  420. result = result + ' ' + self.command[item];
  421. } else {
  422. result = result + ' ' + item;
  423. }
  424. });
  425. if (result === ' nagios_update_ignore ACTIONEXECUTE') {
  426. result = Em.I18n.t('common.maintenance.task');
  427. }
  428. return result;
  429. },
  430. /**
  431. * Convert uppercase status name to downcase.
  432. * <br>
  433. * <br>PENDING - Not queued yet for a host
  434. * <br>QUEUED - Queued for a host
  435. * <br>IN_PROGRESS - Host reported it is working
  436. * <br>COMPLETED - Host reported success
  437. * <br>FAILED - Failed
  438. * <br>TIMEDOUT - Host did not respond in time
  439. * <br>ABORTED - Operation was abandoned
  440. *
  441. * @memberof App.format
  442. * @method taskStatus
  443. * @param {string} _taskStatus
  444. * @return {string}
  445. *
  446. */
  447. taskStatus:function (_taskStatus) {
  448. return _taskStatus.toLowerCase();
  449. }
  450. };
  451. /**
  452. * wrapper to bootstrap popover
  453. * fix issue when popover stuck on view routing
  454. *
  455. * @memberof App
  456. * @method popover
  457. * @param {DOMElement} self
  458. * @param {object} options
  459. */
  460. App.popover = function(self, options) {
  461. self.popover(options);
  462. self.on("remove", function () {
  463. $(this).trigger('mouseleave');
  464. });
  465. };
  466. /**
  467. * wrapper to bootstrap tooltip
  468. * fix issue when tooltip stuck on view routing
  469. * @memberof App
  470. * @method tooltip
  471. * @param {DOMElement} self
  472. * @param {object} options
  473. */
  474. App.tooltip = function(self, options) {
  475. self.tooltip(options);
  476. /* istanbul ignore next */
  477. self.on("remove", function () {
  478. $(this).trigger('mouseleave');
  479. });
  480. };
  481. /**
  482. * wrapper to Date().getTime()
  483. * fix issue when client clock and server clock not sync
  484. *
  485. * @memberof App
  486. * @method dateTime
  487. * @return {Number} timeStamp of current server clock
  488. */
  489. App.dateTime = function() {
  490. return new Date().getTime() + App.clockDistance;
  491. };
  492. /**
  493. * Helper function for bound property helper registration
  494. * @memberof App
  495. * @method registerBoundHelper
  496. * @param name {String} name of helper
  497. * @param view {Em.View} view
  498. */
  499. App.registerBoundHelper = function(name, view) {
  500. Em.Handlebars.registerHelper(name, function(property, options) {
  501. options.hash.contentBinding = property;
  502. return Em.Handlebars.helpers.view.call(this, view, options);
  503. });
  504. };
  505. /*
  506. * Return singular or plural word based on Em.I18n property key.
  507. *
  508. * Example: {{pluralize hostsCount singular="t:host" plural="t:hosts"}}
  509. */
  510. App.registerBoundHelper('pluralize', Em.View.extend({
  511. tagName: 'span',
  512. template: Em.Handlebars.compile('{{view.wordOut}}'),
  513. wordOut: function() {
  514. var count, singular, plural;
  515. count = this.get('content');
  516. singular = this.get('singular');
  517. plural = this.get('plural');
  518. return this.getWord(count, singular, plural);
  519. }.property('content'),
  520. getWord: function(count, singular, plural) {
  521. singular = this.tDetect(singular);
  522. plural = this.tDetect(plural);
  523. if (singular && plural) {
  524. if (count > 1) {
  525. return plural;
  526. } else {
  527. return singular;
  528. }
  529. }
  530. return '';
  531. },
  532. /*
  533. * Detect for Em.I18n.t reference call
  534. * @params word {String}
  535. * return {String}
  536. */
  537. tDetect: function(word) {
  538. var splitted = word.split(':');
  539. if (splitted.length > 1 && splitted[0] == 't') {
  540. return Em.I18n.t(splitted[1]);
  541. } else {
  542. return splitted[0];
  543. }
  544. }
  545. })
  546. );
  547. /**
  548. * Return defined string instead of empty if value is null/undefined
  549. * by default is `n/a`.
  550. *
  551. * @param empty {String} - value instead of empty string (not required)
  552. * can be used with Em.I18n pass value started with't:'
  553. *
  554. * Examples:
  555. *
  556. * default value will be returned
  557. * {{formatNull service.someValue}}
  558. *
  559. * <code>empty<code> will be returned
  560. * {{formatNull service.someValue empty="I'm empty"}}
  561. *
  562. * Em.I18n translation will be returned
  563. * {{formatNull service.someValue empty="t:my.key.to.translate"
  564. */
  565. App.registerBoundHelper('formatNull', Em.View.extend({
  566. tagName: 'span',
  567. template: Em.Handlebars.compile('{{view.result}}'),
  568. result: function() {
  569. var emptyValue = this.get('empty') ? this.get('empty') : Em.I18n.t('services.service.summary.notAvailable');
  570. emptyValue = emptyValue.startsWith('t:') ? Em.I18n.t(emptyValue.substr(2, emptyValue.length)) : emptyValue;
  571. return (this.get('content') || this.get('content') == 0) ? this.get('content') : emptyValue;
  572. }.property('content')
  573. }));
  574. /**
  575. * Return formatted string with inserted <code>wbr</code>-tag after each dot
  576. *
  577. * @param {String} content
  578. *
  579. * Examples:
  580. *
  581. * returns 'apple'
  582. * {{formatWordBreak 'apple'}}
  583. *
  584. * returns 'apple.<wbr />banana'
  585. * {{formatWordBreak 'apple.banana'}}
  586. *
  587. * returns 'apple.<wbr />banana.<wbr />uranium'
  588. * {{formatWordBreak 'apple.banana.uranium'}}
  589. */
  590. App.registerBoundHelper('formatWordBreak', Em.View.extend({
  591. tagName: 'span',
  592. template: Em.Handlebars.compile('{{{view.result}}}'),
  593. /**
  594. * @type {string}
  595. */
  596. result: function() {
  597. return this.get('content') && this.get('content').replace(/\./g, '.<wbr />');
  598. }.property('content')
  599. }));
  600. /**
  601. * Ambari overrides the default date transformer.
  602. * This is done because of the non-standard data
  603. * sent. For example Nagios sends date as "12345678".
  604. * The problem is that it is a String and is represented
  605. * only in seconds whereas Javascript's Date needs
  606. * milliseconds representation.
  607. */
  608. DS.attr.transforms.date = {
  609. from: function (serialized) {
  610. var type = typeof serialized;
  611. if (type === Em.I18n.t('common.type.string')) {
  612. serialized = parseInt(serialized);
  613. type = typeof serialized;
  614. }
  615. if (type === Em.I18n.t('common.type.number')) {
  616. if (!serialized ){ //serialized timestamp = 0;
  617. return 0;
  618. }
  619. // The number could be seconds or milliseconds.
  620. // If seconds, then the length is 10
  621. // If milliseconds, the length is 13
  622. if (serialized.toString().length < 13) {
  623. serialized = serialized * 1000;
  624. }
  625. return new Date(serialized);
  626. } else if (serialized === null || serialized === undefined) {
  627. // if the value is not present in the data,
  628. // return undefined, not null.
  629. return serialized;
  630. } else {
  631. return null;
  632. }
  633. },
  634. to: function (deserialized) {
  635. if (deserialized instanceof Date) {
  636. return deserialized.getTime();
  637. } else if (deserialized === undefined) {
  638. return undefined;
  639. } else {
  640. return null;
  641. }
  642. }
  643. };
  644. DS.attr.transforms.object = {
  645. from: function(serialized) {
  646. return Ember.none(serialized) ? null : Object(serialized);
  647. },
  648. to: function(deserialized) {
  649. return Ember.none(deserialized) ? null : Object(deserialized);
  650. }
  651. };
  652. /**
  653. * Allows EmberData models to have array properties.
  654. *
  655. * Declare the property as <code>
  656. * operations: DS.attr('array'),
  657. * </code> and
  658. * during load provide a JSON array for value.
  659. *
  660. * This transform simply assigns the same array in both directions.
  661. */
  662. DS.attr.transforms.array = {
  663. from : function(serialized) {
  664. return serialized;
  665. },
  666. to : function(deserialized) {
  667. return deserialized;
  668. }
  669. };