PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/StarterTemplates/ConsoleAppHost/default.htm

http://github.com/ServiceStack/ServiceStack.Examples
HTML | 688 lines | 599 code | 87 blank | 2 comment | 0 complexity | b3baac8dae6333fb76bfbe33cb312bae MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Backbone Demo: Todos</title>
  5. <script>window.JSON || document.write('<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js">\x3C/script>')</script>
  6. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
  7. <script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.6/underscore-min.js"></script>
  8. <script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"></script>
  9. <script type="text/javascript">
  10. // An example Backbone application contributed by
  11. // [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple
  12. // [LocalStorage adapter](backbone-localstorage.html)
  13. // to persist Backbone models within your browser.
  14. // Load the application once the DOM is ready, using `jQuery.ready`:
  15. var todosUrl = "todos";
  16. $(function () {
  17. // Todo Model
  18. // ----------
  19. // Our basic **Todo** model has `content`, `order`, and `done` attributes.
  20. window.Todo = Backbone.Model.extend({
  21. // Default attributes for the todo.
  22. defaults: {
  23. Content: "empty todo...",
  24. Done: false
  25. },
  26. // Ensure that each todo created has `content`.
  27. initialize: function () {
  28. if (!this.get("Content")) {
  29. this.set({ "Content": this.defaults.Content });
  30. }
  31. },
  32. // Toggle the `done` state of this todo item.
  33. toggle: function () {
  34. this.save({ Done: !this.get("Done") });
  35. },
  36. url: function () {
  37. return this.get("Id") ? todosUrl + '/' + this.get("Id") : todosUrl;
  38. },
  39. // Remove this Todo from *localStorage* and delete its view.
  40. clear: function () {
  41. this.destroy();
  42. this.view.remove();
  43. }
  44. });
  45. // Todo Collection
  46. // ---------------
  47. // The collection of todos is backed by *localStorage* instead of a remote
  48. // server.
  49. window.TodoList = Backbone.Collection.extend({
  50. // Reference to this collection's model.
  51. model: Todo,
  52. // Save all of the todo items under the `"todos"` namespace.
  53. //localStorage: new Store("todos"),
  54. url: todosUrl,
  55. // Filter down the list of all todo items that are finished.
  56. done: function () {
  57. return this.filter(function (todo) { return todo.get('Done'); });
  58. },
  59. // Filter down the list to only todo items that are still not finished.
  60. remaining: function () {
  61. return this.without.apply(this, this.done());
  62. },
  63. // We keep the Todos in sequential order, despite being saved by unordered
  64. // GUID in the database. This generates the next order number for new items.
  65. nextOrder: function () {
  66. if (!this.length) return 1;
  67. return this.last().get('Order') + 1;
  68. },
  69. // Todos are sorted by their original insertion order.
  70. comparator: function (todo) {
  71. return todo.get('Order');
  72. }
  73. });
  74. // Create our global collection of **Todos**.
  75. window.Todos = new TodoList;
  76. // Todo Item View
  77. // --------------
  78. // The DOM element for a todo item...
  79. window.TodoView = Backbone.View.extend({
  80. //... is a list tag.
  81. tagName: "li",
  82. // Cache the template function for a single item.
  83. template: _.template($('#item-template').html()),
  84. // The DOM events specific to an item.
  85. events: {
  86. "click .check": "toggleDone",
  87. "dblclick div.todo-content": "edit",
  88. "click span.todo-destroy": "clear",
  89. "keypress .todo-input": "updateOnEnter"
  90. },
  91. // The TodoView listens for changes to its model, re-rendering. Since there's
  92. // a one-to-one correspondence between a **Todo** and a **TodoView** in this
  93. // app, we set a direct reference on the model for convenience.
  94. initialize: function () {
  95. _.bindAll(this, 'render', 'close');
  96. this.model.bind('change', this.render);
  97. this.model.view = this;
  98. },
  99. // Re-render the contents of the todo item.
  100. render: function () {
  101. $(this.el).html(this.template(this.model.toJSON()));
  102. this.setContent();
  103. return this;
  104. },
  105. // To avoid XSS (not that it would be harmful in this particular app),
  106. // we use `jQuery.text` to set the contents of the todo item.
  107. setContent: function () {
  108. var content = this.model.get('Content');
  109. this.$('.todo-content').text(content);
  110. this.input = this.$('.todo-input');
  111. this.input.bind('blur', this.close);
  112. this.input.val(content);
  113. },
  114. // Toggle the `"done"` state of the model.
  115. toggleDone: function () {
  116. this.model.toggle();
  117. },
  118. // Switch this view into `"editing"` mode, displaying the input field.
  119. edit: function () {
  120. $(this.el).addClass("editing");
  121. this.input.focus();
  122. },
  123. // Close the `"editing"` mode, saving changes to the todo.
  124. close: function () {
  125. this.model.save({ Content: this.input.val() });
  126. $(this.el).removeClass("editing");
  127. },
  128. // If you hit `enter`, we're through editing the item.
  129. updateOnEnter: function (e) {
  130. if (e.keyCode == 13) this.close();
  131. },
  132. // Remove this view from the DOM.
  133. remove: function () {
  134. $(this.el).remove();
  135. },
  136. // Remove the item, destroy the model.
  137. clear: function () {
  138. this.model.clear();
  139. }
  140. });
  141. // The Application
  142. // ---------------
  143. // Our overall **AppView** is the top-level piece of UI.
  144. window.AppView = Backbone.View.extend({
  145. // Instead of generating a new element, bind to the existing skeleton of
  146. // the App already present in the HTML.
  147. el: $("#todoapp"),
  148. // Our template for the line of statistics at the bottom of the app.
  149. statsTemplate: _.template($('#stats-template').html()),
  150. // Delegated events for creating new items, and clearing completed ones.
  151. events: {
  152. "keypress #new-todo": "createOnEnter",
  153. "keyup #new-todo": "showTooltip",
  154. "click .todo-clear a": "clearCompleted"
  155. },
  156. // At initialization we bind to the relevant events on the `Todos`
  157. // collection, when items are added or changed. Kick things off by
  158. // loading any preexisting todos that might be saved in *localStorage*.
  159. initialize: function () {
  160. _.bindAll(this, 'addOne', 'addAll', 'render');
  161. this.input = this.$("#new-todo");
  162. Todos.bind('add', this.addOne);
  163. Todos.bind('refresh', this.addAll);
  164. Todos.bind('all', this.render);
  165. Todos.fetch();
  166. },
  167. // Re-rendering the App just means refreshing the statistics -- the rest
  168. // of the app doesn't change.
  169. render: function () {
  170. var done = Todos.done().length;
  171. this.$('#todo-stats').html(this.statsTemplate({
  172. Total: Todos.length,
  173. Done: Todos.done().length,
  174. Remaining: Todos.remaining().length
  175. }));
  176. },
  177. // Add a single todo item to the list by creating a view for it, and
  178. // appending its element to the `<ul>`.
  179. addOne: function (todo) {
  180. var view = new TodoView({ model: todo });
  181. this.$("#todo-list").append(view.render().el);
  182. },
  183. // Add all items in the **Todos** collection at once.
  184. addAll: function () {
  185. Todos.each(this.addOne);
  186. },
  187. // Generate the attributes for a new Todo item.
  188. newAttributes: function () {
  189. return {
  190. Content: this.input.val(),
  191. Order: Todos.nextOrder(),
  192. Done: false
  193. };
  194. },
  195. // If you hit return in the main input field, create new **Todo** model,
  196. // persisting it to *localStorage*.
  197. createOnEnter: function (e) {
  198. if (e.keyCode != 13) return;
  199. Todos.create(this.newAttributes());
  200. this.input.val('');
  201. },
  202. // Clear all done todo items, destroying their models.
  203. clearCompleted: function () {
  204. _.each(Todos.done(), function (todo) { todo.clear(); });
  205. return false;
  206. },
  207. // Lazily show the tooltip that tells you to press `enter` to save
  208. // a new todo item, after one second.
  209. showTooltip: function (e) {
  210. var tooltip = this.$(".ui-tooltip-top");
  211. var val = this.input.val();
  212. tooltip.fadeOut();
  213. if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);
  214. if (val == '' || val == this.input.attr('placeholder')) return;
  215. var show = function () { tooltip.show().fadeIn(); };
  216. this.tooltipTimeout = _.delay(show, 1000);
  217. }
  218. });
  219. // Finally, we kick things off by creating the **App**.
  220. window.App = new AppView;
  221. });
  222. </script>
  223. <style type="text/css">
  224. html, body, div, span, applet, object, iframe,
  225. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  226. a, abbr, acronym, address, big, cite, code,
  227. del, dfn, em, font, img, ins, kbd, q, s, samp,
  228. small, strike, strong, sub, sup, tt, var,
  229. dl, dt, dd, ol, ul, li,
  230. fieldset, form, label, legend,
  231. table, caption, tbody, tfoot, thead, tr, th, td {
  232. margin: 0;
  233. padding: 0;
  234. border: 0;
  235. outline: 0;
  236. font-weight: inherit;
  237. font-style: inherit;
  238. font-size: 100%;
  239. font-family: inherit;
  240. vertical-align: baseline;
  241. }
  242. body {
  243. line-height: 1;
  244. color: black;
  245. background: white;
  246. }
  247. ol, ul {
  248. list-style: none;
  249. }
  250. a img {
  251. border: none;
  252. }
  253. html {
  254. background: #eeeeee;
  255. }
  256. body {
  257. font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  258. font-size: 14px;
  259. line-height: 1.4em;
  260. background: #eeeeee;
  261. color: #333333;
  262. }
  263. #todoapp {
  264. width: 480px;
  265. margin: 0 auto 40px;
  266. background: white;
  267. padding: 20px;
  268. -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
  269. -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
  270. -o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
  271. box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
  272. }
  273. #todoapp h1 {
  274. font-size: 36px;
  275. font-weight: bold;
  276. text-align: center;
  277. padding: 20px 0 30px 0;
  278. line-height: 1;
  279. }
  280. #create-todo {
  281. position: relative;
  282. }
  283. #create-todo input {
  284. width: 466px;
  285. font-size: 24px;
  286. font-family: inherit;
  287. line-height: 1.4em;
  288. border: 0;
  289. outline: none;
  290. padding: 6px;
  291. border: 1px solid #999999;
  292. -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  293. -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  294. -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  295. box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  296. }
  297. #create-todo input::-webkit-input-placeholder {
  298. font-style: italic;
  299. }
  300. #create-todo span {
  301. position: absolute;
  302. z-index: 999;
  303. width: 170px;
  304. left: 50%;
  305. margin-left: -85px;
  306. }
  307. #todo-list {
  308. margin-top: 10px;
  309. }
  310. #todo-list li {
  311. padding: 12px 20px 11px 0;
  312. position: relative;
  313. font-size: 24px;
  314. line-height: 1.1em;
  315. border-bottom: 1px solid #cccccc;
  316. }
  317. #todo-list li:after {
  318. content: "\0020";
  319. display: block;
  320. height: 0;
  321. clear: both;
  322. overflow: hidden;
  323. visibility: hidden;
  324. }
  325. #todo-list li.editing {
  326. padding: 0;
  327. border-bottom: 0;
  328. }
  329. #todo-list .editing .display,
  330. #todo-list .edit {
  331. display: none;
  332. }
  333. #todo-list .editing .edit {
  334. display: block;
  335. }
  336. #todo-list .editing input {
  337. width: 444px;
  338. font-size: 24px;
  339. font-family: inherit;
  340. margin: 0;
  341. line-height: 1.6em;
  342. border: 0;
  343. outline: none;
  344. padding: 10px 7px 0px 27px;
  345. border: 1px solid #999999;
  346. -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  347. -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  348. -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  349. box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
  350. }
  351. #todo-list .check {
  352. position: relative;
  353. top: 9px;
  354. margin: 0 10px 0 7px;
  355. float: left;
  356. }
  357. #todo-list .done .todo-content {
  358. text-decoration: line-through;
  359. color: #777777;
  360. }
  361. #todo-list .todo-destroy {
  362. position: absolute;
  363. right: 5px;
  364. top: 14px;
  365. display: none;
  366. cursor: pointer;
  367. width: 20px;
  368. height: 20px;
  369. background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAoCAYAAAD+MdrbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAc1JREFUeNrMVsFKw0AQTWIR+gdCrwUFQZSEgv5CQRAEwYPgKfdCC4JHvRTsR3gTAoLQn5AEvSgKxZwEv6EQ0jdlLJtld5OYFfrgHTqbebubmcyrG8exo8AGeAyegtvgPsdfwU8wAp/ATE5sKcRI4B7sKdZ85jn4DF7wBit4UsIAfNGIyejxswOd4Bi8A9tOdbQ5ZywLnoFD5+8YssZScJN3aYob0vK4kh3VE77vV4oxuqRFgn2TmCigiknou+jDD26VyqdJkkQnmNIJt3SrqkSDGKHjOXYxJ8Ef3WrNohC+STApE6Nrilc1iCYkODW9P1FIFZMwpSpTY79xHzVBCu7QCefgtYWCXP0WhfAAThqITVijMG1GfNJ5nTbhnJFqfNH0vQX3eHiWgZ454JzMNLFpAh+BJzw4ujylHW6xlK/3qLSAMAx1J8iEhEy65uq37Enr5ylBENj3FIja9xSILj3FxYdOn96XzgZqYAbuGj2FNqwYK/cUIdEtiRU8xROaVkYuCbmaNRGHRk/RJObr4yk1i2L2FMU7yyuI6j1FEMhLYgVP8fjf6MxCUWisRVY9BaPMnqdA7H88paXwlMgwYGVPucTJ3ssmdiNPWQgwAJAGndsKbcIpAAAAAElFTkSuQmCC) no-repeat 0 0;
  370. }
  371. #todo-list li:hover .todo-destroy {
  372. display: block;
  373. }
  374. #todo-list .todo-destroy:hover {
  375. background-position: 0 -20px;
  376. }
  377. #todo-stats {
  378. *zoom: 1;
  379. margin-top: 10px;
  380. color: #777777;
  381. }
  382. #todo-stats:after {
  383. content: "\0020";
  384. display: block;
  385. height: 0;
  386. clear: both;
  387. overflow: hidden;
  388. visibility: hidden;
  389. }
  390. #todo-stats .todo-count {
  391. float: left;
  392. }
  393. #todo-stats .todo-count .number {
  394. font-weight: bold;
  395. color: #333333;
  396. }
  397. #todo-stats .todo-clear {
  398. float: right;
  399. }
  400. #todo-stats .todo-clear a {
  401. color: #777777;
  402. font-size: 12px;
  403. }
  404. #todo-stats .todo-clear a:visited {
  405. color: #777777;
  406. }
  407. #todo-stats .todo-clear a:hover {
  408. color: #336699;
  409. }
  410. #instructions {
  411. width: 520px;
  412. margin: 10px auto;
  413. color: #777777;
  414. text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
  415. text-align: center;
  416. }
  417. #instructions a {
  418. color: #336699;
  419. }
  420. #credits {
  421. width: 520px;
  422. margin: 30px auto;
  423. color: #999;
  424. text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
  425. text-align: center;
  426. }
  427. #credits a {
  428. color: #888;
  429. }
  430. /*
  431. * François 'cahnory' Germain
  432. */
  433. .ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left {
  434. color:#ffffff;
  435. cursor:normal;
  436. display:-moz-inline-stack;
  437. display:inline-block;
  438. font-size:12px;
  439. font-family:arial;
  440. padding:.5em 1em;
  441. position:relative;
  442. text-align:center;
  443. text-shadow:0 -1px 1px #111111;
  444. -webkit-border-top-left-radius:4px ;
  445. -webkit-border-top-right-radius:4px ;
  446. -webkit-border-bottom-right-radius:4px ;
  447. -webkit-border-bottom-left-radius:4px ;
  448. -khtml-border-top-left-radius:4px ;
  449. -khtml-border-top-right-radius:4px ;
  450. -khtml-border-bottom-right-radius:4px ;
  451. -khtml-border-bottom-left-radius:4px ;
  452. -moz-border-radius-topleft:4px ;
  453. -moz-border-radius-topright:4px ;
  454. -moz-border-radius-bottomright:4px ;
  455. -moz-border-radius-bottomleft:4px ;
  456. border-top-left-radius:4px ;
  457. border-top-right-radius:4px ;
  458. border-bottom-right-radius:4px ;
  459. border-bottom-left-radius:4px ;
  460. -o-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
  461. -moz-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
  462. -khtml-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
  463. -webkit-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
  464. box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
  465. background-color:#3b3b3b;
  466. background-image:-moz-linear-gradient(top,#555555,#222222);
  467. background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#555555),color-stop(1,#222222));
  468. filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
  469. -ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
  470. }
  471. .ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after {
  472. content:"\25B8";
  473. display:block;
  474. font-size:2em;
  475. height:0;
  476. line-height:0;
  477. position:absolute;
  478. }
  479. .ui-tooltip:after, .ui-tooltip-bottom:after {
  480. color:#2a2a2a;
  481. bottom:0;
  482. left:1px;
  483. text-align:center;
  484. text-shadow:1px 0 2px #000000;
  485. -o-transform:rotate(90deg);
  486. -moz-transform:rotate(90deg);
  487. -khtml-transform:rotate(90deg);
  488. -webkit-transform:rotate(90deg);
  489. width:100%;
  490. }
  491. .ui-tooltip-top:after {
  492. bottom:auto;
  493. color:#4f4f4f;
  494. left:-2px;
  495. top:0;
  496. text-align:center;
  497. text-shadow:none;
  498. -o-transform:rotate(-90deg);
  499. -moz-transform:rotate(-90deg);
  500. -khtml-transform:rotate(-90deg);
  501. -webkit-transform:rotate(-90deg);
  502. width:100%;
  503. }
  504. .ui-tooltip-right:after {
  505. color:#222222;
  506. right:-0.375em;
  507. top:50%;
  508. margin-top:-.05em;
  509. text-shadow:0 1px 2px #000000;
  510. -o-transform:rotate(0);
  511. -moz-transform:rotate(0);
  512. -khtml-transform:rotate(0);
  513. -webkit-transform:rotate(0);
  514. }
  515. .ui-tooltip-left:after {
  516. color:#222222;
  517. left:-0.375em;
  518. top:50%;
  519. margin-top:.1em;
  520. text-shadow:0 -1px 2px #000000;
  521. -o-transform:rotate(180deg);
  522. -moz-transform:rotate(180deg);
  523. -khtml-transform:rotate(180deg);
  524. -webkit-transform:rotate(180deg);
  525. }
  526. </style>
  527. </head>
  528. <body>
  529. <!-- Todo App Interface -->
  530. <div id="todoapp">
  531. <div class="title">
  532. <h1>Todos</h1>
  533. </div>
  534. <div class="content">
  535. <div id="create-todo">
  536. <input id="new-todo" placeholder="What needs to be done?" type="text" />
  537. <span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span>
  538. </div>
  539. <div id="todos">
  540. <ul id="todo-list"></ul>
  541. </div>
  542. <div id="todo-stats"></div>
  543. </div>
  544. </div>
  545. <ul id="instructions">
  546. <li>Double-click to edit a todo.</li>
  547. <li><a href="https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/StarterTemplates/StarterTemplates.Common/TodoService.cs">Source code of C# TODO REST Service</a> | <a href="http://documentcloud.github.com/backbone/examples/todos/index.html">Backbone.js TODO app</a> </li>
  548. </ul>
  549. <div id="credits">
  550. Created by
  551. <br />
  552. <a href="http://jgn.me/">J&eacute;r&ocirc;me Gravel-Niquet</a>
  553. <br />
  554. <br />
  555. Powered By Open Source
  556. <br />
  557. <a href="http://servicestack.net">servicestack.net</a>
  558. | <a href="http://redis.io">redis</a>
  559. | <a href="http://www.mono-project.com">mono</a>
  560. </div>
  561. <!-- Templates -->
  562. <script type="text/template" id="item-template">
  563. <div class="todo <%= Done ? 'Done' : '' %>">
  564. <div class="display">
  565. <input class="check" type="checkbox" <%= Done ? 'checked="checked"' : '' %> />
  566. <div class="todo-content"></div>
  567. <span class="todo-destroy"></span>
  568. </div>
  569. <div class="edit">
  570. <input class="todo-input" type="text" value="" />
  571. </div>
  572. </div>
  573. </script>
  574. <script type="text/template" id="stats-template">
  575. <% if (Total) { %>
  576. <span class="todo-count">
  577. <span class="number"><%= Remaining %></span>
  578. <span class="word"><%= Remaining == 1 ? 'item' : 'items' %></span> left.
  579. </span>
  580. <% } %>
  581. <% if (Done) { %>
  582. <span class="todo-clear">
  583. <a href="#">
  584. Clear <span class="number-done"><%= Done %></span>
  585. completed <span class="word-done"><%= Done == 1 ? 'item' : 'items' %></span>
  586. </a>
  587. </span>
  588. <% } %>
  589. </script>
  590. <script type="text/javascript">
  591. var _gaq = _gaq || [];
  592. _gaq.push(['_setAccount', 'UA-7722718-7']);
  593. _gaq.push(['_trackPageview']);
  594. (function () {
  595. var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  596. ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  597. var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  598. })();
  599. </script>
  600. </body>
  601. </html>