PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/www/js/app.js

https://bitbucket.org/izalutsky/vchat
JavaScript | 446 lines | 313 code | 53 blank | 80 comment | 5 complexity | b0951c1cb24fed26f793311448769cbc MD5 | raw file
  1. (function(){
  2. "use strict";
  3. if (!window.vchat) {
  4. window.vchat = {};
  5. }
  6. var vchat = window.vchat;
  7. /**
  8. * Wraps the iScroll object, providing fix() workaround for content scrolling too high
  9. * @param nodeId id of scroller DOM element
  10. * @constructor
  11. */
  12. function ScrollWrapper(nodeId){
  13. /*jshint newcap:false */
  14. this.lastScrollY = 0;
  15. this.offset = 50;
  16. this.node = document.getElementById(nodeId);
  17. this.iScroll = new iScroll(nodeId);
  18. }
  19. /**
  20. * Limits maximum scrolling offset
  21. */
  22. ScrollWrapper.prototype.fix = function(){
  23. /*
  24. if (this.iScroll.maxScrollY !== this.iScroll.lastScrollY) {
  25. this.iScroll.maxScrollY += this.node.offsetHeight - this.offset;
  26. this.lastScrollY = this.iScroll.maxScrollY;
  27. }
  28. */
  29. };
  30. /**
  31. * Creates an object with precompiled templating methods
  32. * @param {String[]} names Array of template names
  33. * @constructor
  34. */
  35. function Templater(){
  36. var that = this;
  37. var templates = $("[data-template-name]");
  38. templates.each(function(){
  39. var element = $(this);
  40. var name = element.attr("data-template-name");
  41. var source = element.html();
  42. that[name] = Handlebars.compile(source);
  43. });
  44. }
  45. /*
  46. Application start code. Exeduted before creation of any models or views
  47. */
  48. var templater = new Templater();
  49. /**
  50. * Model of Dashboard entity
  51. * @type {*}
  52. */
  53. var BoardModel = Backbone.Model.extend({
  54. defaults: {
  55. boardInfo: ''
  56. },
  57. initialize: function()
  58. {
  59. var that = this;
  60. $.get(
  61. "http://vapes.ws/videochat/mobile/readboard.php",
  62. function(data)
  63. {
  64. console.log(data);
  65. that.set({
  66. boardInfo: data
  67. });
  68. }
  69. );
  70. }
  71. });
  72. /**
  73. * Model of a single chat message
  74. * @type {*}
  75. */
  76. var ChatMessageModel = Backbone.Model.extend({
  77. defaults: {
  78. userName: "",
  79. text: ""
  80. },
  81. initialize: function(){
  82. }
  83. });
  84. /**
  85. * Collection of tweets
  86. * @type {*}
  87. */
  88. var ChatList = Backbone.Collection.extend({
  89. model: ChatMessageModel
  90. });
  91. /**
  92. * Model of Chat entity
  93. * @type {*}
  94. */
  95. var ChatModel = Backbone.Model.extend({
  96. defaults: {
  97. timeout: 1000 * 2,
  98. chatUrl: 'http://vapes.ws/videochat/mobile/readchatmessages.php',
  99. chatText: '',
  100. chats: new ChatList()
  101. },
  102. initialize: function()
  103. {
  104. var that = this;
  105. that.startPoll();
  106. },
  107. startPoll: function(){
  108. var that = this;
  109. that.getMessages();
  110. setTimeout(function(){
  111. that.startPoll();
  112. }, that.get("timeout"));
  113. },
  114. getMessages: function()
  115. {
  116. var model = this;
  117. console.log(model.get("chatUrl"));
  118. $.getJSON(model.get("chatUrl"), function(data){
  119. console.log(data);
  120. model.addMessages(data);
  121. });
  122. },
  123. addMessages: function(chats)
  124. {
  125. var chatMessageModels = _.map(chats, function(chat){
  126. console.log(chat.userName);
  127. return new ChatMessageModel({
  128. userName: chat.userName,
  129. text: chat.userMessage
  130. });
  131. });
  132. var collection = this.get("chats");
  133. collection.reset(chatMessageModels);
  134. this.trigger("change");
  135. }
  136. });
  137. /**
  138. * Model of Geolocation entity
  139. * @type {*}
  140. */
  141. var LocationModel = Backbone.Model.extend({
  142. defaults: {
  143. url: "http://vapes.ws/videochat/mobile/readlatlng.php",
  144. lat: 0,
  145. lng: 0
  146. },
  147. initialize: function(){
  148. var that = this;
  149. $.getJSON(
  150. that.get("url"),
  151. function(data){
  152. if (data){
  153. that.set({
  154. lat: data.lat,
  155. lng: data.lng
  156. });
  157. }
  158. }
  159. );
  160. }
  161. });
  162. /**
  163. * Model of a single tweet
  164. * @type {*}
  165. */
  166. var TweetModel = Backbone.Model.extend({
  167. defaults: {
  168. userName: "",
  169. text: "",
  170. picUrl: ""
  171. },
  172. initialize: function(){
  173. }
  174. });
  175. /**
  176. * Collection of tweets
  177. * @type {*}
  178. */
  179. var TweetList = Backbone.Collection.extend({
  180. model: TweetModel
  181. });
  182. /* TODO refactor URLs to baseUrl */
  183. /**
  184. * Model of Twitter entity
  185. * @type {*}
  186. */
  187. var TwitterModel = Backbone.Model.extend({
  188. defaults: {
  189. timeout: 1000 * 60,
  190. tagUrl: "http://vapes.ws/videochat/mobile/readtweettag.php",
  191. queryUrl: "http://vapes.ws/videochat/mobile/tweetSearch.php?act=search&q=",
  192. tweets: new TweetList()
  193. },
  194. initialize: function(){
  195. var that = this;
  196. that.get("tweets").on("change", function(){ // passing collection change event to current model
  197. that.trigger("change");
  198. });
  199. this.startPoll();
  200. },
  201. startPoll: function(){
  202. var that = this;
  203. that.queryTag();
  204. setTimeout(function(){
  205. that.startPoll();
  206. }, that.get("timeout"));
  207. },
  208. queryTag: function(){
  209. var model = this;
  210. $.getJSON(model.get("tagUrl"), function(data){
  211. var query = data.tag;
  212. model.queryTweets(query);
  213. });
  214. },
  215. queryTweets: function(query){
  216. var model = this;
  217. $.getJSON(model.get("queryUrl") + query, function(response){
  218. model.addTweets(response.results);
  219. });
  220. },
  221. addTweets: function(tweets){
  222. var tweetModels = _.map(tweets, function(tweet){
  223. return new TweetModel({
  224. userName: tweet.from_user,
  225. text: tweet.text,
  226. picUrl: tweet.profile_image_url
  227. });
  228. });
  229. var collection = this.get("tweets");
  230. collection.reset(tweetModels);
  231. this.trigger("change");
  232. }
  233. });
  234. //TODO implement videochat model
  235. /**
  236. * Main view of Dashboard entity
  237. * @type {*}
  238. */
  239. var BoardView = Backbone.View.extend({
  240. initialize: function()
  241. {
  242. this.el = $("#text");
  243. this.model.on("change", this.render, this);
  244. this.iscroll = new ScrollWrapper("board");
  245. },
  246. render: function(){
  247. this.el.html(this.model.get("boardInfo"));
  248. this.iscroll.fix();
  249. }
  250. });
  251. //TODO implement chat and message views
  252. var ChatView = Backbone.View.extend({
  253. el: $("#chat"),
  254. initialize: function()
  255. {
  256. this.userMessage = $("#userMessage");
  257. //this.el = $("#chat");
  258. //this.el2 = $("#chatMessages2");
  259. this.model.on("change", this.render, this);
  260. },
  261. events:
  262. {
  263. "click #sendMessage": "onSendMessage"
  264. },
  265. render: function(){
  266. var json = {
  267. chats: this.model.get("chats").toJSON()
  268. };
  269. var chatM = templater.chats(json);
  270. //this.el.children("#chatMessages").html(chatM);
  271. var messages = this.$("#chatMessages");
  272. messages.html(chatM);
  273. //this.el2.html(chatM);
  274. /*jshint newcap:false */
  275. var scroll = new iScroll("chatMessages");
  276. var height = messages.height();
  277. scroll.pageY = height;
  278. //var scroll2 = new iScroll("chatMessages2");
  279. },
  280. onSendMessage: function()
  281. {
  282. var uName = window.vchat.userName;
  283. var uMessage = this.userMessage.val().trim();
  284. console.log(uName);
  285. console.log(uMessage);
  286. $.post('http://vapes.ws/videochat/mobile/server.php', {user: uName, msg: uMessage}, function(response){
  287. console.log("mess send");
  288. $("#userMessage").val("");
  289. });
  290. }
  291. });
  292. /**
  293. * Main view of Geolocation entity as a map
  294. * @type {*}
  295. */
  296. var LocationView = Backbone.View.extend({
  297. initialize: function(){
  298. this.leafletScriptPath = "./leaflet/leaflet.js";
  299. vchat.loader.require(this.leafletScriptPath);
  300. this.el = $("#map");
  301. this.minZoom = 3;
  302. this.maxZoom = 18;
  303. this.initialZoom = 13;
  304. this.model.on("change", this.render, this);
  305. },
  306. render: function(){
  307. var view = this;
  308. // setting fixed height to map container due to Leaflet requirements
  309. this.el.height(this.el.parent().height());
  310. // map needs Leaflet script to be loaded before rendering
  311. vchat.loader.require(this.leafletScriptPath, function(){
  312. var map = new L.Map('map');
  313. var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
  314. var osmAttrib = 'Map data © OpenStreetMap contributors';
  315. var osm = new L.TileLayer(osmUrl, {
  316. minZoom: view.minZoom,
  317. maxZoom: view.maxZoom,
  318. attribution: osmAttrib
  319. });
  320. var latitude = view.model.get("lat");
  321. var longitude = view.model.get("lng");
  322. map.setView(new L.LatLng(latitude, longitude), view.initialZoom);
  323. map.addLayer(osm);
  324. L.marker([latitude, longitude]).addTo(map);
  325. });
  326. }
  327. });
  328. /**
  329. * Main view of Twitter entity as a list of tweets
  330. * @type {*}
  331. */
  332. var TwitterView = Backbone.View.extend({
  333. initialize: function(){
  334. this.model.on("change", this.render, this);
  335. this.el = $("#tweets");
  336. },
  337. render: function(){
  338. var json = {
  339. tweets: this.model.get("tweets").toJSON()
  340. };
  341. var markup = templater.tweets(json);
  342. this.el.html(markup);
  343. /*jshint newcap:false */
  344. var scroll = new iScroll("twitter");
  345. }
  346. });
  347. //TODO implement video chat view with HTML5 Video
  348. var location = new LocationModel();
  349. var map = new LocationView({ model: location });
  350. var boardModel = new BoardModel();
  351. var borderView = new BoardView({ model: boardModel });
  352. var chatModel = new ChatModel();
  353. var chatView = new ChatView({ model: chatModel });
  354. var twitter = new TwitterModel();
  355. var twitterView = new TwitterView({model: twitter});
  356. var PageRouter = Backbone.Router.extend({
  357. initialize: function(){
  358. var that = this;
  359. that.currentPageName = null;
  360. that.pages = {};
  361. that.links = {};
  362. $("nav a").each(function(){
  363. var link = $(this);
  364. var pageName = link.attr("href").slice(1);
  365. that.links[pageName] = link;
  366. that.pages[pageName] = $("#" + pageName);
  367. });
  368. },
  369. routes: {
  370. ":pageName": "pageRoute"
  371. },
  372. pageRoute: function(pageName) {
  373. var lastPage = this.currentPageName;
  374. if (lastPage) {
  375. this.pages[lastPage].css("visibility", "hidden");
  376. this.links[lastPage].removeClass("selected");
  377. }
  378. if (this.pages[pageName]) {
  379. this.pages[pageName].css("visibility", "visible");
  380. this.links[pageName].addClass("selected");
  381. this.currentPageName = pageName;
  382. } else {
  383. console.log("No such page: " + pageName);
  384. }
  385. }
  386. });
  387. var router = new PageRouter();
  388. Backbone.history.start();
  389. router.navigate("chat", {
  390. replace: true,
  391. trigger: true
  392. });
  393. }());