PageRenderTime 6ms CodeModel.GetById 1ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 0ms

/xplorer/js/forkan.js

https://bitbucket.org/itkane/forkan
JavaScript | 768 lines | 404 code | 160 blank | 204 comment | 7 complexity | 4e252a784143e58232dddeee8db5a709 MD5 | raw file
  1
  2// usage: log('inside coolFunc', this, arguments);
  3// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
  4window.log = function(){
  5  log.history = log.history || [];   // store logs to an array for reference
  6  log.history.push(arguments);
  7  if(this.console) {
  8    arguments.callee = arguments.callee.caller;
  9    var newarr = [].slice.call(arguments);
 10    (typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
 11  }
 12};
 13
 14// make it safe to use console.log always
 15(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
 16{console.log();return window.console;}catch(err){return window.console={};}})());
 17
 18
 19// Load the application once the DOM is ready, using `jQuery.ready`:
 20$(function(){
 21 
 22    var cfg ={};
 23	cfg = {
 24			ApiServer  : "http://127.0.0.1/forkan/api/",
 25			version    : "2.0",
 26			key        : "28e336ac6c9423d946ba02d19c6a2632",
 27			riwaya     : "1", // riwaya  [1:hafs 2:warch ...]
 28			tafseer    : "1", // Tafseer [1:tabari 2:jalalyn ...] 
 29			telawa     : "1", // Telawa  [1:Sudais 2:Afasy ...] 
 30			StartPage   : "50",
 31			NavigationMethod: 0,//[0: (d) Navigation with Quran page(604p), 1: custome per ayas]
 32            url : function(){
 33                return /*'http://localhost/forkan/xplorer/'*/this.ApiServer + this.version +'/'+ this.key ;
 34            }
 35			};  
 36
 37			
 38//#############################################################################
 39//-------------------------------------- Aya ----------------------------------
 40  
 41// Aya Model
 42  var modAya = Backbone.Model.extend({
 43  // Our basic **Aya** model has [index, sura, aya, text, riwaya, audio  and views] attributes.
 44    defaults: {
 45      //yid   : 0,
 46      //sur   : 0,
 47      snm   : 0,//sura name (from suras)
 48      //aya   : 0,
 49      //txt   : '',
 50      rwy   : 0,/*,
 51	  audio  : '',
 52	  views  : 0,*/
 53	  active : false
 54    },
 55	// index
 56	idAttribute: "yid",
 57    initialize: function() {
 58	  if(_.isUndefined(this.get('yid'))){ 
 59		//this.destroy();
 60		//alert('empty');
 61      }
 62	  else{
 63	  //--- make attr more readable then "array[x]
 64	    this.set({yid : this.get("yid"),
 65	            sur  : this.get("sur"),
 66	            aya   : this.get("aya"),
 67	            txt  : this.get("txt")
 68	            //"riwaya": this.get("rw")
 69				});
 70				
 71		//alert(JSON.stringify(this));
 72		}
 73    },
 74
 75    focus: function() {
 76      this.set({"active" :true});
 77    },
 78    blur: function() {
 79      this.set({"active" :true});
 80    },
 81    clear: function() {
 82      this.destroy();
 83    }
 84
 85  });
 86
 87// Ayas Collection
 88  var colAyas = Backbone.Collection.extend({
 89
 90    // Reference to this collection's model.
 91    model: modAya,
 92	  
 93	/*url: function(){
 94        //var arg={cls:"q",act:"get",ayaID:1,nbr:17};
 95		return "/aya";
 96	},*/
 97
 98	parse: function(response) {
 99       return response.dt;
100    },
101    // Filter down the list of all todo items that are finished.
102    /*done: function() {
103      return this.filter(function(todo){ return todo.get('done'); });
104    },*/
105
106
107
108    // Ayas are sorted by their original insertion order.
109    comparator: function(mod) {
110      return mod.get('order');
111    }
112
113  });
114
115// Aya Item View
116  var viewAya = Backbone.View.extend({
117
118    //... is a list tag.
119    tagName:  "span",
120    className:"iAyaCon",
121	//el: $(".iAya"),
122	
123    // Cache the template function for a single item.
124    template: _.template($('#aya-template').html()),
125    SideTemplate : _.template($('#side-template').html()),
126
127    // The DOM events specific to an item.
128    events: {
129      "hover .iAya"                 : "iHover",
130      "click .iAya"                 : "iFocus"
131    },
132	
133    initialize: function() {
134      _.bindAll(this, 'render', 'close'/*, 'remove'*/);
135      this.model.bind('change', this.render);
136      this.model.bind('destroy', this.remove);
137
138    },
139
140    // Re-render the contents of the todo item.
141    render: function() {
142		var aya = this;
143		
144		/*var pg = Forkan.Pages.find(function(page){
145			(page.get('pid') == aya.model.get('sur')) { aya.model.set({'snm':sura.get('nam')});}
146		return (sura.get('sid') == aya.model.get('sur'));});*/
147		
148		aya.model.set({'snm':Forkan.Suras.get(aya.model.get('sur')).get('nam')});
149		//aya.model.set({'pid':Forkan.Pages.get(aya.model.get('sur')).get('nam')});
150			
151      $(this.el).html(this.template(this.model.toJSON()));
152      return this;
153    },
154
155    // On Hover on Aya.
156    iHover: function() {
157      $(this.el).find(".iAya").toggleClass("ayaHover");
158      
159    },
160
161    // On click or focus on Aya.
162    iFocus: function() {
163		$(".iAya").removeClass("ayaActive");
164		$(this.el).find(".iAya").addClass("ayaActive");
165		$("#iside").html(this.SideTemplate(this.model.toJSON()));
166		
167		var aya = this;
168		
169		// change currents breadcrumbe
170		Forkan.Suras.get(aya.model.get('sur')).active();
171		
172		/*var ss = Forkan.Suras.models;
173		var ps = Forkan.Pages.models;
174		//alert(JSON.stringify(ss[5].get('sta')));
175		var p = Forkan.Pages.find(function(page){
176			if(page.get('pid')){
177			var p1 = ps[page.get('pid')]; //console.log('p1='+p1.get('pid'));
178			var p2 = ps[(parseInt(page.get('pid'))+1)]; //console.log('p2='+p1.get('pid'));
179			
180			var sur = ss[page.get('sur')];//console.log('s1='+sur.get('sid'));
181			var sur2= ss[p2.get('sur')];  //console.log('s2='+sur2.get('sid'));
182			
183			var start = parseInt(sur.get('sta'))+parseInt(page.get('aya'))-1;
184			var end = sur2.get('sta') ;
185			//var end   = start + page.get('pid')+1].get('ays');
186			console.log('s:'+start+' e:'+end+' y:'+aya.model.get('yid'));
187			//console.log('p1='+p1.get('pid')+' p2='+p2.get('pid')+' s1='+sur.get('sid')+' s2='+sur2.get('sid'));
188			
189			return (aya.model.get('yid') >= start) && (aya.model.get('yid') < end);
190			}
191		});
192		//alert(JSON.stringify(p));
193		p.active();
194	  */
195    },
196
197
198    close: function() {
199        $(this.el).unbind();
200        $(this.el).empty();
201    },
202    // Remove the item, destroy the model.
203    clear: function() {
204      this.model.clear();
205    }
206
207  });
208
209// maybe add AyasView 4 search result  
210
211// Ayas List View
212  var viewAyas = Backbone.View.extend({
213    el: $('#ipage'),
214    
215    initialize: function() {
216        this.model.bind("reset", this.render, this);
217    },
218    render: function(eventName) {
219        //$(this.el).empty();
220		_.each(this.model.models, function(iModel) {
221			
222            //TODO: add cfg 4: append vs prepend
223			
224			if(!_.isUndefined(iModel.get('yid'))){
225			  $(this.el).prepend(
226                new viewAya({model: iModel}).render().el);
227			}
228        }, this);
229		//this.last.
230		//$('.iAya').first().click();
231        return this;
232    }
233});
234
235
236//#############################################################################
237//---------------------------------- Pages ------------------------------------
238
239// Page Item Model
240var modPage = Backbone.Model.extend({
241    //urlRoot: cfg.url()+"/page",
242    defaults: {
243        "pid": 0,
244        "sur":  "",
245        "aya":  ""
246      }, 
247	// index
248	idAttribute: "pid",
249	  
250	initialize: function() {
251      //if (!this.get("index")) {
252		//this.destroy();
253      //};
254	  //--- make attr more readable then "array[x]
255	  this.set({"pid" : this.get("pid"),
256	            "sur"  : this.get("sur"),
257	            "aya"   : this.get("aya")
258				});
259				
260		//alert(JSON.stringify(this));
261    }
262});
263
264// Page Item View
265var viewPage = Backbone.View.extend({
266 
267    tagName: "li",
268 
269    template: _.template($('#page-template').html()),
270 
271    events: {
272      "click .iPage"                 : "select"
273    }, 
274    initialize: function() {
275        this.model.bind("change", this.render, this);
276        this.model.bind("destroy", this.close, this);
277    },
278 
279    render: function(eventName) {
280        $(this.el).html(this.template(this.model.toJSON()));
281        return this;
282    },
283 
284 
285    select: function() {
286        var page = this.model; 
287		this.active();
288        Forkan.navigate("ayas/page/"+page.get("pid"), true);
289    },
290    active: function() {
291        var page = this.model; 
292        $('#activePage').html(page.get('pid'));
293    },
294	
295    close: function() {
296        $(this.el).unbind();
297        $(this.el).remove();
298    }
299});
300
301
302// Pages List Collection
303var colPages = Backbone.Collection.extend({
304    model : modPage,
305    url : function(){
306        return 'ayas/page';
307    },
308	parse: function(response) {
309       return response.dt;
310    }
311});
312
313// Pages List View
314var viewPages = Backbone.View.extend({
315    el: $('#pageList'),
316    
317    initialize: function() {
318        this.model.bind("reset", this.render, this);
319    },
320    render: function(eventName) {
321        _.each(this.model.models, function(iModel) {
322            //TODO: add cfg 4: append vs prepend
323			$(this.el).prepend(
324                new viewPage({model: iModel}).render().el);
325        }, this);
326        return this;
327    }
328});
329
330 
331//############################################################################# 
332//-------------------------------- Suras Collection ---------------------------
333
334// Sura Item Model
335  var modSura = Backbone.Model.extend({
336  //[start, ayas, order, rukus, name, tname, ename, type] attributes.
337  //[0, 7, 5, 1, '???????', "Al-Faatiha", 'The Opening', 'Meccan'],
338
339    defaults: {
340     /*  sid  : 0,
341      sta  : 0,
342      ays   : 0,
343      ord  : 0,
344      rukus  : 0,
345      nam   : '',
346	  tnm  : '',
347	  enm  : '',
348	  typ   : '',
349      audio  : ''*/
350    },
351	// index
352	idAttribute: "sid",
353
354    initialize: function() {
355	  if(_.isUndefined(this.get('0'))){ 
356		//this.destroy();
357		//alert('empty');
358      }
359	  else{
360	  //--- make attr more readable then "array[x]
361		this.set({"sta" : this.get("1"),
362	            "sid"  : this.get("0"),
363	            "ays"  : this.get("2"),
364	            "ord" : this.get("3"),
365	            //"rukus" : this.get("rukus"),
366	            "nam"  : this.get("5"),
367	            //"tname" : this.get("tname"),
368	            "enm" : this.get("4"),
369	            "typ"  : this.get("6")
370	            //"audio" : this.get("audio")
371	            //"riwaya": this.get("rw")
372				});
373				
374		//alert(JSON.stringify(this));
375		//alert(JSON.stringify(this.get('5')));
376		}
377    },
378    active: function(){
379	    $('#activeSura').html(this.get('nam'));
380	},
381    // Remove this Todo from *localStorage* and delete its view.
382    clear: function() {
383      this.destroy();
384    }
385
386  });
387
388// Suras List Collection
389  var colSuras = Backbone.Collection.extend({
390
391    model: modSura,
392	  
393	/*url: function(){
394		return '/sura';//+cfg.StartAya+"/nbr=15";
395	},*/
396
397	parse: function(response) {
398       return response.dt;
399    }
400
401  });
402
403
404// Sura Item View
405  var viewSura = Backbone.View.extend({
406 
407    tagName: "li",
408    className:"iSuraCon",
409 
410    template: _.template($('#sura-template').html()),
411
412    events: {
413      "click .iSura"                 : "select"
414    }, 
415	
416    initialize: function() {
417        this.model.bind("change", this.render, this);
418        this.model.bind("destroy", this.close, this);
419    },
420 
421    render: function(eventName) {
422        $(this.el).html(this.template(this.model.toJSON()));
423        return this;
424    },
425 
426    select: function() {
427        var sura = this.model; 
428		this.active();
429        Forkan.navigate("ayas/"+(sura.get("sta"))+'/to/'+sura.get("ays"), true);
430    },
431    active: function() {
432        var sura = this.model; 
433        $('#activeSura').html(sura.get('nam'));
434    },
435 	
436    close: function() {
437        $(this.el).unbind();
438        $(this.el).remove();
439    }
440    
441
442
443
444  });
445
446// Sura List View
447  var viewSuras = Backbone.View.extend({
448    el: $('#suraList'),
449    
450    initialize: function() {
451        this.model.bind("reset", this.render, this);
452        this.model.bind("active", this.active, this);
453    },
454    render: function(eventName) {
455		$(this.el).empty();
456        _.each(this.model.models, function(iModel) {
457            //TODO: add cfg 4: append vs prepend
458			if(!_.isUndefined(iModel.get('sid'))){
459			$(this.el).prepend(
460                new viewSura({model: iModel}).render().el);
461			}
462        }, this);
463        return this;
464    },
465    active: function() {
466        var sura = this.model; 
467        $('#activeSura').html(sura.get('nam'));
468    }
469});
470  
471  
472  // The Application
473  // ---------------
474//var Ayas = new colAyas;
475//var Suras = new colSuras;
476//var Ayas = new colAyas;
477  // Our overall **AppView** is the top-level piece of UI.
478  var AppView = Backbone.View.extend({
479
480    // Instead of generating a new element, bind to the existing skeleton of
481    // the App already present in the HTML.
482    el: $("#forkanApp"),
483
484    // Our template for the line of statistics at the bottom of the app.
485    //statsTemplate: _.template($('#stats-template').html()),
486
487    // Delegated events for creating new items, and clearing completed ones.
488    events: {
489      //"keypress #new-todo":  "createOnEnter",
490      //"keyup #new-todo":     "showTooltip",
491      //"click .iSura": "GotoSura",
492      //"click .mark-all-done": "toggleAllComplete"
493    },
494
495    initialize: function() {
496      //_.bindAll(this, 'addAya', 'addAyas', 'addSura', 'addSuras', 'render');/, 'toggleAllComplete'
497
498      //this.input = this.$("#new-todo");
499      //this.allCheckbox = this.$(".mark-all-done")[0];
500
501      /*Forkan.Ayas.bind('add',     this.render);
502      Forkan.Ayas.bind('reset',   this.render);
503      Forkan.Ayas.bind('all',     this.render);
504      
505      Forkan.Suras.bind('add',     this.render);
506      Forkan.Suras.bind('reset',   this.render);
507      Forkan.Suras.bind('all',     this.render);*/
508
509      
510    },
511
512    // Re-rendering the App just means refreshing the statistics -- the rest
513    // of the app doesn't change.
514    render: function() {
515	  
516            $("*[rel=twipsy]").twipsy({
517               live: true
518            });
519			$("*[rel=popover]")
520                .popover({
521                  offset: 10
522                })
523                .click(function(e) {
524                  e.preventDefault()
525                });
526
527			$('.dropdown').dropdown();
528			
529	},
530    // Add a single todo item to the list by creating a view for it, and
531    // appending its element to the `<ul>`.
532    addAya: function(aya) {
533      var view = new viewAya({model: aya});
534      this.$("#ipage").prepend(view.render().el);
535    },
536
537    // Add all items in the **Todos** collection at once.
538    addAyas: function() {
539      Ayas.each(this.addAya);
540    },
541    // Add a single todo item to the list by creating a view for it, and
542    // appending its element to the `<ul>`.
543    addSura: function(sura) {
544      var view = new viewSura({model: sura});
545      $("#suraList").append(view.render().el);
546      
547    },
548
549    // Add all items in the **Todos** collection at once.
550    addSuras: function() {
551      Suras.each(this.addSura);
552    },
553
554    // Generate the attributes for a new Todo item.
555    newAttributes: function() {
556
557    }
558
559
560
561    // Lazily show the tooltip that tells you to press `enter` to save
562    // a new todo item, after one second.
563    /*showTooltip: function(e) {
564      var tooltip = this.$(".ui-tooltip-top");
565      var val = this.input.val();
566      tooltip.fadeOut();
567      if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);
568      if (val == '' || val == this.input.attr('placeholder')) return;
569      var show = function(){ tooltip.show().fadeIn(); };
570      this.tooltipTimeout = _.delay(show, 1000);
571    },*/
572
573
574  });
575
576
577
578 
579var AppRouter = Backbone.Router.extend({
580 
581    routes: {
582        "ayas/:id/to/:nbr"  : "getAyas",
583        "ayas/page/:id"     : "getAyasPerPage",
584        "ayas/page/:id/:yid": "gotoAyaInPage",
585        "page"              : "getPages",
586        ""                  : "home",
587    },
588	init: function(){
589        var self = this;
590		// initialize All object
591		
592        this.Ayas   = new colAyas();
593        this.Suras  = new colSuras();
594		this.Suras.fetch({
595			url : cfg.ApiServer + cfg.version +'/'+ cfg.key+'/suras',
596			success: function() {
597		    	self.SurasView = new viewSuras({model: self.Suras});
598				self.SurasView.render();
599				//if (self.requestedId) self.getAya(self.requestedId);
600		/*self.Ayas.fetch({
601			url : cfg.url()+"/ayas/page/"+cfg.StartPage,
602			success: function() {
603		    	self.AyasView = new viewAyas({model: self.Ayas});
604				self.AyasView.render();
605				// focus in first aya
606				$('.iAya').first().click();
607				//if (self.requestedId) self.getAya(self.requestedId);
608			}
609		});*/
610		
611	Backbone.history.start();
612			}
613		});
614	  Forkan.Ayas.bind('add',     this.irender);
615      Forkan.Ayas.bind('reset',   this.irender);
616      Forkan.Ayas.bind('all',     this.irender);
617      
618      Forkan.Suras.bind('add',     this.irender);
619      Forkan.Suras.bind('reset',   this.irender);
620      Forkan.Suras.bind('all',     this.irender);
621		
622
623		
624        this.Pages  = new colPages();
625		this.Pages.fetch({
626			url : cfg.ApiServer + cfg.version +'/'+ cfg.key+'/pages',
627			success: function() {
628			    
629		    	self.PagesView = new viewPages({model: self.Pages});
630				self.PagesView.render();
631				//if (self.requestedId) self.getAya(self.requestedId);
632				$('#pg'+cfg.startPage).click();
633				
634			}
635		});
636	  
637	  
638	},    
639
640	irender: function() {
641	  
642            $("*[rel=twipsy]").twipsy({
643               live: true
644            });
645			$("*[rel=popover]")
646                .popover({
647                  offset: 10
648                })
649                .click(function(e) {
650                  e.preventDefault()
651                });
652
653			$('.dropdown').dropdown();
654			
655			
656	},
657 
658    home: function() {
659        var self = this;
660		if (!self.requestedId){
661		self.Ayas.fetch({
662			url : cfg.url()+"/ayas/page/"+cfg.StartPage,
663			success: function() {
664		    	self.AyasView = new viewAyas({model: self.Ayas});
665				self.AyasView.render();
666				// focus in first aya
667				$('.iAya').first().click();
668				//if (self.requestedId) self.getAya(self.requestedId);
669			}
670		});}   
671    },
672    
673    getAyas: function(id,nbr) {
674		var self = this;
675		self.requestedId = id;
676		//if (!this.Ayas){this.init();}
677              
678		$("#ipage").animate({right: '-500px'},"700",function() { $(this).hide().empty() });
679
680
681         this.Ayas.fetch({
682				url : cfg.url()+"/ayas/"+id+"/to/"+nbr,
683                success: function() {
684				//$("#ipage").slideDown();				
685				$("#ipage").animate({right: '0px'},"700",function() { $(this).show() });
686		    	/* ; //self.AyasView = new viewAyas({model: self.Ayas});
687				//self.AyasView.render();
688                    //if (self.requestedId) self.wineDetails(self.requestedId);*/
689            }
690        });
691
692    } , 
693	
694    getAyasPerPage: function(id) {
695		var self = this;
696		
697		self.requestedId = id;
698		//if (!this.Ayas){this.init();}
699              
700		$("#ipage").animate({right: '-500px'},"700",function() { $(this).hide().empty() });
701
702
703         this.Ayas.fetch({
704				url : cfg.url()+"/ayas/page/"+id,
705                success: function() {
706				//$("#ipage").slideDown();				
707				$("#ipage").animate({right: '0px'},"700",function() { $(this).show() });
708
709				// focus in first aya
710				$('.iAya').first().click();
711            }
712        });
713
714    } ,
715	
716    gotoAyaInPage: function(id,yid) {
717		var self = this;
718
719		self.requestedId = id;		
720		//if (!this.Ayas){this.init();}
721              
722		$("#ipage").animate({right: '-500px'},"700",function() { $(this).hide().empty() });
723
724
725         this.Ayas.fetch({
726				url : cfg.url()+"/ayas/page/"+id,
727                success: function() {
728				//$("#ipage").slideDown();				
729				$("#ipage").animate({right: '0px'},"700",function() { $(this).show();
730				$("#ya"+yid).click(); });
731				// focus in aya
732		    	/* ; //self.AyasView = new viewAyas({model: self.Ayas});
733				//self.AyasView.render();
734                    //if (self.requestedId) self.wineDetails(self.requestedId);*/
735            }
736        });
737
738    } ,
739
740    getPages: function() {
741		var self = this;
742		
743		//if (!this.Ayas){this.init();}
744              
745         this.Pages.fetch({
746				url : cfg.hh.url()+"/aya/"+id+"/to/"+nbr/* ; 
747                success: function() {
748				$("#ipage").empty();
749		    	//self.AyasView = new viewAyas({model: self.Ayas});
750				//self.AyasView.render();
751                    //if (self.requestedId) self.wineDetails(self.requestedId);
752            }*/
753        });
754		
755    }
756 
757});
758 
759  
760var Forkan = new AppRouter();
761
762	Forkan.init();
763    Forkan.view = new AppView;
764	
765	//var header = new HeaderView();
766  // Finally, we kick things off by creating the **App**.
767
768});