<commit_before>// GiftCardService service
NGApp.factory( 'GiftCardService', function( $http, $location, $rootScope, AccountModalService, CreditService, RestaurantsService ){

	var service = {
		redeemed : false,
		code : false,
		value : '',
		notes_field : { lastValidation: '', content : '', giftcards : { success : [], error : [] }, value : '0.00', removed : false, id_restaurant : null, hasGiftCards : false, restaurant_accepts : false }, /* Notes field */
		modal : {
			intro : true,
			error : false,
			success : false,
			restaurant : false,
		}
	};

	credit = CreditService;

	service.accountModal = AccountModalService;
	service.account = service.accountModal.facebook.account;

	service.open = function(){
		App.dialog.show( '.giftcard-container' );
		service.parseURLCode();
		if( service.modal.intro ){
			setTimeout( function(){
				service.processModal();
				$location.path( '/location' );
			}, 100 );
		}
	}

	service.openRestaurant = function(){
		$location.path( '/' + RestaurantsService.permalink + '/' + service.modal.restaurant.permalink );
		service.modal.close();
	}

	service.parseURLCode = function(){
		service.code = $location.path().replace( '/giftcard', '' );
		service.code = service.code.replace( '/', '' );
	}

	/* Register the view */
	service.viewed = function(){
		var url = App.service + 'giftcard/viewed';
		$http( {
			method: 'POST',
			url: url,
			data: $.param( { 'code' : service.code } ),
			headers: {'Content-Type': 'application/x-www-form-urlencoded'}
			} );
	}

	service.processModal = function(){
		if( !service.code || service.code == '' ){
			return;
		}

		if( !(/^\w+$/.test( $.trim( service.code ) )) ){
			service.code = '';
			return;
		}
		service.modal.reset();
		setTimeout( function(){

			// Do not auto redeem gift cards #1662
			service.redeemed = false;

			service.validate( function( data ){

				service.modal.intro = false;
				if( data.error ){
					service.modal.error = true;
					switch( data.error ){
						case 'gift card already used':
							service.viewed();
							service.modal.error = 'used';
							break;
						case 'invalid gift card':
							service.modal.error = 'invalid';
							break;
						default:
							service.modal.error = 'unknow';
							break;
					}
					service.code = false;
				} else if ( data.success ){
					service.viewed();
					service.modal.success = true;
					service.value = data.success['value'];
					if( data.success['id_restaurant'] ){
						service.modal.restaurant = { id_restaurant : data.success['id_restaurant'], name : data.success['restaurant'], permalink : data.success['permalink'] };
					} else {
						service.modal.restaurant = false;
					}
					$rootScope.$broadcast( 'GiftCardProcessed', true );
					if( service.redeemed ){
						service.code = '';
					}
				}
			} );

		}, 500 );
	}

	service.modal.reset = function(){
		service.modal.intro = true;
		service.modal.error = false;
		service.modal.success = false;
		service.modal.restaurant = false;
	}

	service.modal.signIn = function(){
		service.account.callback = function(){
			service.open();
			service.processModal();
		}
		service.modal.close();
		setTimeout( function(){
			service.accountModal.signinOpen();
		}, 500 );
	}

	service.modal.close = function(){
		$.magnificPopup.close();
	}

	// Validates a gift card code
	service.validate = function( callback ){
		service.code = $.trim( service.code );
		if( service.code == '' ){
			callback( { error : true } );
			return;
		}
		if( service.redeemed ){
			var url = App.service + 'giftcard/code';
		} else {
			var url = App.service + 'giftcard/validate';
		}
		$http( {
			method: 'POST',
			url: url,
			data: $.param( { 'code' : service.code } ),
			headers: {'Content-Type': 'application/x-www-form-urlencoded'}
			} ).success( function( data ) {
				callback( data );
			}	).error(function( data, status ) {
				callback( { error : true } );
			} );
	}

	service.notes_field.reset = function(){
		service.notes_field.content = '';
		service.notes_field.giftcards = { success : [], error : [] };
		service.notes_field.value = '0.00';
		service.notes_field.removed = false;
		service.notes_field.id_restaurant = null;
		service.notes_field.hasGiftCards = false;
		service.notes_field.restaurant_accepts = false;
		service.code = false;
	}

	service.notes_field.start = function(){

		service.notes_field.hasGiftCards = false;

		if( service.notes_field.content == '' ){
			service.notes_field.giftcards.success = [];
		}

		if( service.notes_field.content && service.notes_field.content != '' ){

		var words = service.notes_field.content;

		if( words == service.notes_field.lastValidation ){
			return;
		}

		service.notes_field.lastValidation = words;

		if( !service.notes_field.running ){

			service.notes_field.running = true;

			var url = App.service + 'giftcard/validate-words';

			$http( {
				method: 'POST',
				url: url,
				data: $.param( { 'words' : words } ),
				headers: {'Content-Type': 'application/x-www-form-urlencoded'}
				} ).success( function( data ) {
					if( data.success ){
						service.notes_field.hasGiftCards = true;
						var giftcard = data.success;
						if( giftcard.id_restaurant &&  giftcard.id_restaurant != service.notes_field.id_restaurant ){
							giftcard.error = 'other restaurant';
						}
						service.notes_field.giftcards.success.push( data.success );
					} else if( data.error ){
						service.notes_field.giftcards.success = [];
					}
					service.notes_field.total--;
					service.notes_field.checkAllValidated();
					service.notes_field.running = false;
				}	).error(function( data, status ) { service.notes_field.total--; service.notes_field.checkAllValidated();  service.notes_field.running = false; } );
			}
		}
	}

	service.notes_field.checkAllValidated = function(){
		service.notes_field.compareValues();
		$rootScope.$broadcast( 'giftCardUpdate' );
	}

	service.notes_field.compareValues = function(){
		service.notes_field.removed = false;
		var values = 0;
		if( service.notes_field.giftcards.success.length > 0 ){
			$.each( service.notes_field.giftcards.success, function( key, giftcard ) {
				console.log('giftcard',giftcard);
				if( giftcard && !giftcard.error ){
					values += parseFloat( giftcard.value );
				}
			} );
		}

		if( service.notes_field.value > values ){
			service.notes_field.removed = true;
		}

		if( service.notes_field.restaurant_accepts ){
			service.notes_field.value = App.ceil( values ).toFixed( 2 );
			credit.setValue( App.ceil( credit.redeemed + values ).toFixed( 2 ) );
		}
		$rootScope.$broadcast( 'creditChanged',  { value : service.value } );
	}

	return service;

} );

NGApp.factory( 'CreditService', function( $http, $rootScope ){

	var service = { value : '0.00', tooltip : false, redeemed : 0 };

	service.setValue = function( value ){
		service.value = value;
		$rootScope.$broadcast( 'creditChanged',  { value : service.value } );
	}

	service.getCredit = function( restaurant_id ){
		var url = App.service + 'user/credit/' + restaurant_id;
		$http( { url: url } ).success( function( data ) {
			if( data.credit ){
				service.setValue( App.ceil( data.credit ).toFixed( 2 ) );
				service.redeemed = data.credit;
			} else {
				service.setValue( App.ceil( 0 ).toFixed( 2 ) );
				service.redeemed = 0;
			}
		}	).error(function() {
				service.setValue( App.ceil( 0 ).toFixed( 2 ) );
				service.redeemed = 0;
		} );
	}
	return service;
} );

<commit_msg>partial #1836<commit_after>// GiftCardService service
NGApp.factory( 'GiftCardService', function( $http, $location, $rootScope, AccountModalService, CreditService, RestaurantsService ){

	var service = {
		redeemed : false,
		code : false,
		value : '',
		notes_field : { lastValidation: '', content : '', giftcards : { success : [], error : [] }, value : '0.00', removed : false, id_restaurant : null, hasGiftCards : false, restaurant_accepts : false }, /* Notes field */
		modal : {
			intro : true,
			error : false,
			success : false,
			restaurant : false,
		}
	};

	credit = CreditService;

	service.accountModal = AccountModalService;
	service.account = service.accountModal.facebook.account;

	service.open = function(){
		App.dialog.show( '.giftcard-container' );
		service.parseURLCode();
		if( service.modal.intro ){
			setTimeout( function(){
				service.processModal();
				$location.path( '/location' );
			}, 100 );
		}
	}

	service.openRestaurant = function(){
		$location.path( '/' + RestaurantsService.permalink + '/' + service.modal.restaurant.permalink );
		service.modal.close();
	}

	service.parseURLCode = function(){
		service.code = $location.path().replace( '/giftcard', '' );
		service.code = service.code.replace( '/', '' );
	}

	/* Register the view */
	service.viewed = function(){
		var url = App.service + 'giftcard/viewed';
		$http( {
			method: 'POST',
			url: url,
			data: $.param( { 'code' : service.code } ),
			headers: {'Content-Type': 'application/x-www-form-urlencoded'}
			} );
	}

	service.processModal = function(){
		if( !service.code || service.code == '' ){
			return;
		}

		if( !(/^\w+$/.test( $.trim( service.code ) )) ){
			service.code = '';
			return;
		}
		service.modal.reset();
		setTimeout( function(){

			// Do not auto redeem gift cards #1662
			service.redeemed = false;

			service.validate( function( data ){

				service.modal.intro = false;
				if( data.error ){
					service.modal.error = true;
					switch( data.error ){
						case 'gift card already used':
							service.viewed();
							service.modal.error = 'used';
							break;
						case 'invalid gift card':
							service.modal.error = 'invalid';
							break;
						default:
							service.modal.error = 'unknow';
							break;
					}
					service.code = false;
				} else if ( data.success ){
					service.viewed();
					service.modal.success = true;
					service.value = data.success['value'];
					if( data.success['id_restaurant'] ){
						service.modal.restaurant = { id_restaurant : data.success['id_restaurant'], name : data.success['restaurant'], permalink : data.success['permalink'] };
					} else {
						service.modal.restaurant = false;
					}
					$rootScope.$broadcast( 'GiftCardProcessed', true );
					if( service.redeemed ){
						service.code = '';
					}
				}
			} );

		}, 500 );
	}

	service.modal.reset = function(){
		service.modal.intro = true;
		service.modal.error = false;
		service.modal.success = false;
		service.modal.restaurant = false;
	}

	service.modal.signIn = function(){
		service.account.callback = function(){
			service.open();
			service.processModal();
		}
		service.modal.close();
		setTimeout( function(){
			service.accountModal.signinOpen();
		}, 500 );
	}

	service.modal.close = function(){
		$.magnificPopup.close();
	}

	// Validates a gift card code
	service.validate = function( callback ){
		service.code = $.trim( service.code );
		if( service.code == '' ){
			callback( { error : true } );
			return;
		}
		if( service.redeemed ){
			var url = App.service + 'giftcard/code';
		} else {
			var url = App.service + 'giftcard/validate';
		}
		$http( {
			method: 'POST',
			url: url,
			data: $.param( { 'code' : service.code } ),
			headers: {'Content-Type': 'application/x-www-form-urlencoded'}
			} ).success( function( data ) {
				callback( data );
			}	).error(function( data, status ) {
				callback( { error : true } );
			} );
	}

	service.notes_field.reset = function(){
		service.notes_field.content = '';
		service.notes_field.giftcards = { success : [], error : [] };
		service.notes_field.value = '0.00';
		service.notes_field.removed = false;
		service.notes_field.id_restaurant = null;
		service.notes_field.hasGiftCards = false;
		service.notes_field.restaurant_accepts = false;
		service.code = false;
	}

	service.notes_field.start = function(){

		service.notes_field.hasGiftCards = false;

		if( service.notes_field.content == '' ){
			service.notes_field.giftcards.success = [];
		}

		if( service.notes_field.content && service.notes_field.content != '' ){

		var words = service.notes_field.content;

		if( words == service.notes_field.lastValidation ){
			return;
		}

		service.notes_field.lastValidation = words;
		if( !service.notes_field.running ){
			service.notes_field.running = true;
			var url = App.service + 'giftcard/validate-words';
			$http( {
				method: 'POST',
				url: url,
				data: $.param( { 'words' : words } ),
				headers: {'Content-Type': 'application/x-www-form-urlencoded'}
				} ).success( function( data ) {
					if( data.success ){
						service.notes_field.hasGiftCards = true;
						var giftcard = data.success;
						if( giftcard.id_restaurant &&  giftcard.id_restaurant != service.notes_field.id_restaurant ){
							giftcard.error = 'other restaurant';
						}
						service.notes_field.giftcards.success.push( data.success );
					} else if( data.error ){
						service.notes_field.giftcards.success = [];
					}
					service.notes_field.total--;
					service.notes_field.checkAllValidated();
					service.notes_field.running = false;
				}	).error(function( data, status ) { service.notes_field.total--; service.notes_field.checkAllValidated();  service.notes_field.running = false; } );
			}
		}
	}

	service.notes_field.checkAllValidated = function(){
		service.notes_field.compareValues();
		$rootScope.$broadcast( 'giftCardUpdate' );
	}

	service.notes_field.compareValues = function(){
		service.notes_field.removed = false;
		var values = 0;
		if( service.notes_field.giftcards.success.length > 0 ){
			$.each( service.notes_field.giftcards.success, function( key, giftcard ) {
				console.log('giftcard',giftcard);
				if( giftcard && !giftcard.error ){
					values += parseFloat( giftcard.value );
				}
			} );
		}

		if( service.notes_field.value > values ){
			service.notes_field.removed = true;
		}

		if( service.notes_field.restaurant_accepts ){
			service.notes_field.value = App.ceil( values ).toFixed( 2 );
			credit.setValue( App.ceil( credit.redeemed + values ).toFixed( 2 ) );
		}
		$rootScope.$broadcast( 'creditChanged',  { value : service.value } );
	}

	return service;

} );

NGApp.factory( 'CreditService', function( $http, $rootScope ){

	var service = { value : '0.00', tooltip : false, redeemed : 0 };

	service.setValue = function( value ){
		service.value = value;
		$rootScope.$broadcast( 'creditChanged',  { value : service.value } );
	}

	service.getCredit = function( restaurant_id ){
		var url = App.service + 'user/credit/' + restaurant_id;
		$http( { url: url } ).success( function( data ) {
			if( data.credit ){
				service.setValue( App.ceil( data.credit ).toFixed( 2 ) );
				service.redeemed = data.credit;
			} else {
				service.setValue( App.ceil( 0 ).toFixed( 2 ) );
				service.redeemed = 0;
			}
		}	).error(function() {
				service.setValue( App.ceil( 0 ).toFixed( 2 ) );
				service.redeemed = 0;
		} );
	}
	return service;
} );

<|endoftext|>


<commit_before>/* Copyright (c) 2012 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
define(function(require, exports, module) {
"use strict";

	console.log("Loading fileOpener...");

	var TSCORE = require("tscore");

	var _openedFilePath = undefined;

	var _isFileOpened = false;

	var _tsEditor = undefined;

	// If a file is currently opened for editing, this var should be true
	var _isEditMode = false;

	function isFileEdited() {
		return _isEditMode;
	}

	function isFileOpened() {
		return _isFileOpened;
	}

	function setFileOpened(fileOpened) {
		_isFileOpened = fileOpened;
	}

	function getOpenedFilePath() {
		return _openedFilePath;
	}

	function openFile(filePath) {
	    console.log("Opening file: "+filePath);

		if(TSCORE.FileOpener.isFileEdited()) {
			if(!confirm("Any unsaved changes will be lost! \nDo you want to continue?")) {
				return false;
			}
		}

	    _isEditMode = false;

	    _openedFilePath = filePath;
	    $("#selectedFilePath").val(_openedFilePath.replace("\\\\","\\"));

	    var fileExt = TSCORE.TagUtils.extractFileExtension(filePath);

	    constructFileViewerUI(filePath);

	    // Getting the viewer for the file extension/type
	    var viewerExt = TSCORE.Config.getFileTypeViewer(fileExt);
	    console.log("File Viewer: "+viewerExt);

	    initTagSuggestionMenu(filePath);

	    $( "#viewer" ).empty();
	    if(!viewerExt) {
	        $( "#viewer" ).html("
Info File type not supported for viewing."+
	                            "<button type='button' class='close' data-dismiss='alert'>×</button>
");
	    } else if (viewerExt == "viewerBrowser") {
		    filePath = "file:///"+filePath;
		    $('#viewer').append($('', {
		    	id: "iframeViewer",
				src: filePath
		    }));
	    } else {
	        require([TSCORE.Config.getExtensionPath()+"/"+viewerExt+"/extension.js"], function(viewer) {
	            _tsEditor = viewer;
	            _tsEditor.init(filePath, "viewer", true);
	        });
	    }
	    TSCORE.FileOpener.setFileOpened(true);
		TSCORE.openFileViewer();
	}

	function updateEditorContent(fileContent) {
	    console.log("Updating editor"); // with data: "+fileContent);
	    _tsEditor.setContent(fileContent);
	}

	// Should return false if no editor found
	function getFileEditor(filePath) {
	    var fileExt = TSCORE.TagUtils.extractFileExtension(filePath);

	    // Getting the editor for the file extension/type
	    var editorExt = TSCORE.Config.getFileTypeEditor(fileExt);
	    console.log("File Editor: "+editorExt);
	    return editorExt;
	}

	function editFile(filePath) {
	    console.log("Editing file: "+filePath);

        $( "#viewer" ).empty();

	    var editorExt = getFileEditor(filePath);
/*	    if(editorExt === false || editorExt == "false" || editorExt == "") {
            $( "#viewer" ).html("
Info File type not supported for editing..");
	        return;
	    } else {*/
	        try {
	            require([TSCORE.Config.getExtensionPath()+"/"+editorExt+"/extension.js"], function(editr) {
	                _tsEditor = editr;
	                _tsEditor.init(filePath, "viewer", false);
	            });
	            _isEditMode = true;
	        } catch(ex) {
	            console.error("Loading editing extension failed: "+ex);
	        }
	   // }
	}

	function saveFile(filePath) {
	    console.log("Save current file: "+filePath);
	    var content = _tsEditor.getContent();
	    TSCORE.IO.saveTextFile(filePath, content);
	}

	function constructFileViewerUI(filePath) {
	    // Adding tag buttons to the filetoolbox
	    var tags = TSCORE.TagUtils.extractTags(filePath);

	    var title = TSCORE.TagUtils.extractTitle(filePath);
		var fileExtension = TSCORE.TagUtils.extractFileExtension(filePath);

		$("#fileTitle").unbind('.editInPlace');
		$("#fileTitle").data('editInPlace',false);

	    $( "#fileTitle" ).text(title);

	    $( "#fileTitle" ).editInPlace({
			callback: function(unused, newTitle) { TSCORE.TagUtils.changeTitle(filePath,newTitle); },
    		show_buttons: false,
    		callback_skip_dom_reset: true
		});

	    // Generate tag & ext buttons
	    $( "#fileTags" ).empty();
        $( "#fileTags" ).append($('<button>', {
                    title: "Opens context menu for "+fileExtension,
                    tag: fileExtension,
                    "class":  "btn btn-small btn-info extTagButton",
                    text: fileExtension+" "
                })
                .click( function() {
                    TSCORE.selectedTag = fileExtension;
                })
                .dropdown( 'attach' , '#extensionMenu' )
                .append($("", { class: "caret"}))
             );

	    for (var i=0; i < tags.length; i++) {
	        $( "#fileTags" ).append($("<button>", {
	            "class":  "btn btn-success btn-small tagButton",
	            tag: tags[i],
	            filepath: filePath,
	            title: "Opens context menu for "+tags[i],
	            text: tags[i]+" "
	            })
	            .append($("", { class: "caret"}))
	            );
	    };

	    $( "#tagsContainer" ).droppable({
	        greedy: "true",
	    	accept: ".tagButton",
	    	hoverClass: "activeRow",
	    	drop: function( event, ui ) {
	    		var tagName = ui.draggable.attr("tag");
				console.log("Tagging file: "+tagName+" to "+filePath);
				TSCORE.TagUtils.addTag([filePath], [tagName]);
				$(ui.helper).remove();
	    	}
	    })

	    // Activate tagButtons in file view
	    $('.tagButton', $( "#fileTags" ))
	        .click( function() {
	            TSCORE.openTagMenu(this, $(this).attr("tag"), $(this).attr("filepath"));
	        })
	        .dropdown( 'attach' , '#tagMenu' );

	    // Clear filetoolbox
	    $( "#filetoolbox" ).empty();

	    $( "#selectedFilePath" ).click(function() {
			this.select();
	    });

        $("#filetoolbox").append('<button id="toggleFullWidthButton" class="btn" title="Toggle Full Width"></button>');
        $("#filetoolbox").append('<button id="prevFileButton" class="btn" title="Go to the previous file"></button>');
        $("#filetoolbox").append('<button id="nextFileButton" class="btn" title="Go to the next file"></button>');
        $("#filetoolbox").append('<button id="editDocument" class="btn" title="Edit File"></button>');
        //$("#filetoolbox").append('<button id="openInNewWindow" class="btn" title="Go to the previous file"></button>');
        $("#filetoolbox").append('<button id="openTagSuggestionMenu" class="btn" title="Tag Suggestions"> </button>');
        //$("#filetoolbox").append('<button id="startFullscreen" class="btn" title="Open file in full screen"></button>');
        $("#filetoolbox").append('<button id="openFileActionsMenu" data-dropdown="#fileActionsMenu" class="btn" title="Opens a menu with additional file actions"> </button>');
        $("#filetoolbox").append('<button id="closeOpenedFile" class="btn" title="Close file"></button>');

        $("#fileActionsMenu").empty();
        //$("#fileActionsMenu").append('
 Edit File
');
        $("#fileActionsMenu").append('
 Show File Details
');
        $("#fileActionsMenu").append('
 Open in New Tab
');
        $("#fileActionsMenu").append('
 Open In Fullscreen
');
        $("#fileActionsMenu").append('
 Print
');

		initFileActions("#filetoolbox", filePath);
	}

	function initTagSuggestionMenu(filePath) {
	    var tags = TSCORE.TagUtils.extractTags(filePath);

	    var suggTags = TSCORE.TagUtils.suggestTags(filePath);

	    var tsMenu = $( "#tagSuggestionsMenu" );

	    $( "#tagSuggestionsMenu" ).empty();

		var suggestionMenuEmpty = true;

	    // Adding context menu entries for creating tags according to the suggested tags
	    for (var i=0; i < suggTags.length; i++) {
	        // Ignoring the tags already assigned to a file
	        if(tags.indexOf(suggTags[i]) < 0) {
	            $( "#tagSuggestionsMenu" ).append($('
', {name: suggTags[i]}).append($('', {
	                title: "Add tag "+suggTags[i]+" to current file",
					tagname: suggTags[i],
					filepath: filePath,
					text: "Tag with '"+suggTags[i]+"'",
	                })
	                .prepend("")
	                .click(function() {
			            var tagName = $(this).attr( "tagname" );
			            var filePath = $(this).attr( "filepath" );
			            console.log("Tag suggestion clicked: "+tagName);
			            TSCORE.TagUtils.writeTagsToFile(filePath, [tagName]);
			          	return false;
	        		})
	               ));
	             suggestionMenuEmpty = false;
	        }
	    };

		// Showing dropdown menu only if the context menus is not empty
		if(!suggestionMenuEmpty) {
	    	$( "#openTagSuggestionMenu" ).dropdown( 'attach' , '#tagSuggestionsMenu' );
		}
	}

	function initFileActions(container, filePath) {
	    var buttonDisabled = false;
	    // If no editor found, disabling the button
	    if(getFileEditor(filePath) === "false") {
	        buttonDisabled = true;
	    }
		var options;

	    $( "#editDocument" ).focus(function() {
	        this.blur();
	    })
	    .click(function() {
            var editorExt = getFileEditor(filePath);
            if(editorExt == false || editorExt == "false" || editorExt == "") {
                TSCORE.showAlertDialog("File type not supported for editing.");
                return false;
            }

			if ( !_isEditMode ) {
				$( this )
				    .attr("title","Save & Close")
				    .html("");
	        	editFile(filePath);
			} else {
			    TSCORE.showConfirmDialog("Confirm","Do you really want to overwrite the current file?", function() {
                    $( "#editDocument" )
                        .attr("title", "Edit File")
                        .html("");
                    _isEditMode = false;
                    saveFile(filePath);
			    });
			}
	    });

        $( "#nextFileButton" ).click(function() {
            TSCORE.FileOpener.openFile(TSCORE.PerspectiveManager.getNextFile(_openedFilePath));
        });

        $( "#prevFileButton" ).click(function() {
            TSCORE.FileOpener.openFile(TSCORE.PerspectiveManager.getPrevFile(_openedFilePath));
        });

        $( "#toggleFullWidthButton" ).click(function() {
            TSCORE.toggleFullWidth();
        });

	    $( "#showFullDetails" ).click(function() {
			TSCORE.toggleFileDetails();
	    });

	    $( "#openInNewWindow" ).click(function() {
	        window.open("file:///"+filePath);
	    });

        $( "#printButton" ).click(function() {
            $('iframe').get(0).contentWindow.print();
        });

        $( "#closeOpenedFile" ).click(function() {
            if(_isEditMode) {
                TSCORE.showConfirmDialog("Confirm","If you confirm, all made changes will be lost.", function() {
                    // Cleaning the viewer/editor
                    document.getElementById("viewer").innerHTML = "";
                    TSCORE.FileOpener.setFileOpened(false);
                    TSCORE.closeFileViewer();
                    _isEditMode = false;
                });
            } else {
                // Cleaning the viewer/editor
                document.getElementById("viewer").innerHTML = "";
                TSCORE.FileOpener.setFileOpened(false);
                TSCORE.closeFileViewer();
                _isEditMode = false;
            }
        });

	    $( "#startFullscreen" ).click(function() {
	        var docElm = $("#viewer")[0];
	        if (docElm.requestFullscreen) {
	            docElm.requestFullscreen();
	        }
	        else if (docElm.mozRequestFullScreen) {
	            docElm.mozRequestFullScreen();
	        }
	        else if (docElm.webkitRequestFullScreen) {
	            docElm.webkitRequestFullScreen();
	        }
	    });
	}

// Methods
    exports.openFile                    		= openFile;
    exports.isFileOpened						= isFileOpened;
    exports.isFileEdited 						= isFileEdited;
    exports.setFileOpened						= setFileOpened;
    exports.getOpenedFilePath             		= getOpenedFilePath;
    exports.updateEditorContent                 = updateEditorContent;

});<commit_msg>added reload current file functionality to the file viewer<commit_after>/* Copyright (c) 2012 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
define(function(require, exports, module) {
"use strict";

	console.log("Loading fileOpener...");

	var TSCORE = require("tscore");

	var _openedFilePath = undefined;

	var _isFileOpened = false;

	var _tsEditor = undefined;

	// If a file is currently opened for editing, this var should be true
	var _isEditMode = false;

	function isFileEdited() {
		return _isEditMode;
	}

	function isFileOpened() {
		return _isFileOpened;
	}

	function setFileOpened(fileOpened) {
		_isFileOpened = fileOpened;
	}

	function getOpenedFilePath() {
		return _openedFilePath;
	}

	function openFile(filePath) {
	    console.log("Opening file: "+filePath);

		if(TSCORE.FileOpener.isFileEdited()) {
			if(!confirm("Any unsaved changes will be lost! \nDo you want to continue?")) {
				return false;
			}
		}

	    _isEditMode = false;

	    _openedFilePath = filePath;
	    $("#selectedFilePath").val(_openedFilePath.replace("\\\\","\\"));

	    var fileExt = TSCORE.TagUtils.extractFileExtension(filePath);

	    constructFileViewerUI(filePath);

	    // Getting the viewer for the file extension/type
	    var viewerExt = TSCORE.Config.getFileTypeViewer(fileExt);
	    console.log("File Viewer: "+viewerExt);

	    initTagSuggestionMenu(filePath);

	    $( "#viewer" ).empty();
	    if(!viewerExt) {
	        $( "#viewer" ).html("
Info File type not supported for viewing."+
	                            "<button type='button' class='close' data-dismiss='alert'>×</button>
");
	    } else if (viewerExt == "viewerBrowser") {
		    filePath = "file:///"+filePath;
		    $('#viewer').append($('', {
		    	id: "iframeViewer",
				src: filePath
		    }));
	    } else {
	        require([TSCORE.Config.getExtensionPath()+"/"+viewerExt+"/extension.js"], function(viewer) {
	            _tsEditor = viewer;
	            _tsEditor.init(filePath, "viewer", true);
	        });
	    }
	    TSCORE.FileOpener.setFileOpened(true);
		TSCORE.openFileViewer();
	}

	function updateEditorContent(fileContent) {
	    console.log("Updating editor"); // with data: "+fileContent);
	    _tsEditor.setContent(fileContent);
	}

	// Should return false if no editor found
	function getFileEditor(filePath) {
	    var fileExt = TSCORE.TagUtils.extractFileExtension(filePath);

	    // Getting the editor for the file extension/type
	    var editorExt = TSCORE.Config.getFileTypeEditor(fileExt);
	    console.log("File Editor: "+editorExt);
	    return editorExt;
	}

	function editFile(filePath) {
	    console.log("Editing file: "+filePath);

        $( "#viewer" ).empty();

	    var editorExt = getFileEditor(filePath);
/*	    if(editorExt === false || editorExt == "false" || editorExt == "") {
            $( "#viewer" ).html("
Info File type not supported for editing..");
	        return;
	    } else {*/
	        try {
	            require([TSCORE.Config.getExtensionPath()+"/"+editorExt+"/extension.js"], function(editr) {
	                _tsEditor = editr;
	                _tsEditor.init(filePath, "viewer", false);
	            });
	            _isEditMode = true;
	        } catch(ex) {
	            console.error("Loading editing extension failed: "+ex);
	        }
	   // }
	}

	function saveFile(filePath) {
	    console.log("Save current file: "+filePath);
	    var content = _tsEditor.getContent();
	    TSCORE.IO.saveTextFile(filePath, content);
	}

	function constructFileViewerUI(filePath) {
	    // Adding tag buttons to the filetoolbox
	    var tags = TSCORE.TagUtils.extractTags(filePath);

	    var title = TSCORE.TagUtils.extractTitle(filePath);
		var fileExtension = TSCORE.TagUtils.extractFileExtension(filePath);

		$("#fileTitle").unbind('.editInPlace');
		$("#fileTitle").data('editInPlace',false);

	    $( "#fileTitle" ).text(title);

	    $( "#fileTitle" ).editInPlace({
			callback: function(unused, newTitle) { TSCORE.TagUtils.changeTitle(filePath,newTitle); },
    		show_buttons: false,
    		callback_skip_dom_reset: true
		});

	    // Generate tag & ext buttons
	    $( "#fileTags" ).empty();
        $( "#fileTags" ).append($('<button>', {
                    title: "Opens context menu for "+fileExtension,
                    tag: fileExtension,
                    "class":  "btn btn-small btn-info extTagButton",
                    text: fileExtension+" "
                })
                .click( function() {
                    TSCORE.selectedTag = fileExtension;
                })
                .dropdown( 'attach' , '#extensionMenu' )
                .append($("", { class: "caret"}))
             );

	    for (var i=0; i < tags.length; i++) {
	        $( "#fileTags" ).append($("<button>", {
	            "class":  "btn btn-success btn-small tagButton",
	            tag: tags[i],
	            filepath: filePath,
	            title: "Opens context menu for "+tags[i],
	            text: tags[i]+" "
	            })
	            .append($("", { class: "caret"}))
	            );
	    };

	    $( "#tagsContainer" ).droppable({
	        greedy: "true",
	    	accept: ".tagButton",
	    	hoverClass: "activeRow",
	    	drop: function( event, ui ) {
	    		var tagName = ui.draggable.attr("tag");
				console.log("Tagging file: "+tagName+" to "+filePath);
				TSCORE.TagUtils.addTag([filePath], [tagName]);
				$(ui.helper).remove();
	    	}
	    })

	    // Activate tagButtons in file view
	    $('.tagButton', $( "#fileTags" ))
	        .click( function() {
	            TSCORE.openTagMenu(this, $(this).attr("tag"), $(this).attr("filepath"));
	        })
	        .dropdown( 'attach' , '#tagMenu' );

	    // Clear filetoolbox
	    $( "#filetoolbox" ).empty();

	    $( "#selectedFilePath" ).click(function() {
			this.select();
	    });

        $("#filetoolbox").append('<button id="toggleFullWidthButton" class="btn" title="Toggle Full Width"></button>');
        $("#filetoolbox").append('<button id="prevFileButton" class="btn" title="Go to the previous file"></button>');
        $("#filetoolbox").append('<button id="nextFileButton" class="btn" title="Go to the next file"></button>');
        $("#filetoolbox").append('<button id="editDocument" class="btn" title="Edit File"></button>');
        //$("#filetoolbox").append('<button id="openInNewWindow" class="btn" title="Go to the previous file"></button>');
        $("#filetoolbox").append('<button id="openTagSuggestionMenu" class="btn" title="Tag Suggestions"> </button>');
        //$("#filetoolbox").append('<button id="startFullscreen" class="btn" title="Open file in full screen"></button>');
        $("#filetoolbox").append('<button id="openFileActionsMenu" data-dropdown="#fileActionsMenu" class="btn" title="Opens a menu with additional file actions"> </button>');
        $("#filetoolbox").append('<button id="closeOpenedFile" class="btn" title="Close file"></button>');

        $("#fileActionsMenu").empty();
        //$("#fileActionsMenu").append('
 Edit File
');
        $("#fileActionsMenu").append('
 Reload File
');
        $("#fileActionsMenu").append('
 Show File Details
');
        $("#fileActionsMenu").append('
 Open in New Tab
');
        $("#fileActionsMenu").append('
 Open In Fullscreen
');
        $("#fileActionsMenu").append('
 Print
');

		initFileActions("#filetoolbox", filePath);
	}

	function initTagSuggestionMenu(filePath) {
	    var tags = TSCORE.TagUtils.extractTags(filePath);

	    var suggTags = TSCORE.TagUtils.suggestTags(filePath);

	    var tsMenu = $( "#tagSuggestionsMenu" );

	    $( "#tagSuggestionsMenu" ).empty();

		var suggestionMenuEmpty = true;

	    // Adding context menu entries for creating tags according to the suggested tags
	    for (var i=0; i < suggTags.length; i++) {
	        // Ignoring the tags already assigned to a file
	        if(tags.indexOf(suggTags[i]) < 0) {
	            $( "#tagSuggestionsMenu" ).append($('
', {name: suggTags[i]}).append($('', {
	                title: "Add tag "+suggTags[i]+" to current file",
					tagname: suggTags[i],
					filepath: filePath,
					text: "Tag with '"+suggTags[i]+"'",
	                })
	                .prepend("")
	                .click(function() {
			            var tagName = $(this).attr( "tagname" );
			            var filePath = $(this).attr( "filepath" );
			            console.log("Tag suggestion clicked: "+tagName);
			            TSCORE.TagUtils.writeTagsToFile(filePath, [tagName]);
			          	return false;
	        		})
	               ));
	             suggestionMenuEmpty = false;
	        }
	    };

		// Showing dropdown menu only if the context menus is not empty
		if(!suggestionMenuEmpty) {
	    	$( "#openTagSuggestionMenu" ).dropdown( 'attach' , '#tagSuggestionsMenu' );
		}
	}

	function initFileActions(container, filePath) {
	    var buttonDisabled = false;
	    // If no editor found, disabling the button
	    if(getFileEditor(filePath) === "false") {
	        buttonDisabled = true;
	    }
		var options;

	    $( "#editDocument" ).focus(function() {
	        this.blur();
	    })
	    .click(function() {
            var editorExt = getFileEditor(filePath);
            if(editorExt == false || editorExt == "false" || editorExt == "") {
                TSCORE.showAlertDialog("File type not supported for editing.");
                return false;
            }

			if ( !_isEditMode ) {
				$( this )
				    .attr("title","Save & Close")
				    .html("");
	        	editFile(filePath);
			} else {
			    TSCORE.showConfirmDialog("Confirm","Do you really want to overwrite the current file?", function() {
                    $( "#editDocument" )
                        .attr("title", "Edit File")
                        .html("");
                    _isEditMode = false;
                    saveFile(filePath);
			    });
			}
	    });

        $( "#nextFileButton" ).click(function() {
            TSCORE.FileOpener.openFile(TSCORE.PerspectiveManager.getNextFile(_openedFilePath));
        });

        $( "#prevFileButton" ).click(function() {
            TSCORE.FileOpener.openFile(TSCORE.PerspectiveManager.getPrevFile(_openedFilePath));
        });

        $( "#toggleFullWidthButton" ).click(function() {
            TSCORE.toggleFullWidth();
        });

        $( "#reloadFile" ).click(function() {
            TSCORE.FileOpener.openFile(_openedFilePath);
        });

	    $( "#showFullDetails" ).click(function() {
			TSCORE.toggleFileDetails();
	    });

	    $( "#openInNewWindow" ).click(function() {
	        window.open("file:///"+filePath);
	    });

        $( "#printButton" ).click(function() {
            $('iframe').get(0).contentWindow.print();
        });

        $( "#closeOpenedFile" ).click(function() {
            if(_isEditMode) {
                TSCORE.showConfirmDialog("Confirm","If you confirm, all made changes will be lost.", function() {
                    // Cleaning the viewer/editor
                    document.getElementById("viewer").innerHTML = "";
                    TSCORE.FileOpener.setFileOpened(false);
                    TSCORE.closeFileViewer();
                    _isEditMode = false;
                });
            } else {
                // Cleaning the viewer/editor
                document.getElementById("viewer").innerHTML = "";
                TSCORE.FileOpener.setFileOpened(false);
                TSCORE.closeFileViewer();
                _isEditMode = false;
            }
        });

	    $( "#startFullscreen" ).click(function() {
	        var docElm = $("#viewer")[0];
	        if (docElm.requestFullscreen) {
	            docElm.requestFullscreen();
	        }
	        else if (docElm.mozRequestFullScreen) {
	            docElm.mozRequestFullScreen();
	        }
	        else if (docElm.webkitRequestFullScreen) {
	            docElm.webkitRequestFullScreen();
	        }
	    });
	}

// Methods
    exports.openFile                    		= openFile;
    exports.isFileOpened						= isFileOpened;
    exports.isFileEdited 						= isFileEdited;
    exports.setFileOpened						= setFileOpened;
    exports.getOpenedFilePath             		= getOpenedFilePath;
    exports.updateEditorContent                 = updateEditorContent;

});<|endoftext|>


<commit_before>define(function(require) {
    'use strict';

    var List = require('../../data/List');
    var completeDimensions = require('../../data/helper/completeDimensions');

    /**
     * Helper function to create a list from option data
     */
    function createListFromArray(data, seriesModel, ecModel) {
        // If data is undefined
        data = data || [];

        var result = creaters[seriesModel.get('coordinateSystem')](
            data, seriesModel, ecModel
        );

        var list = new List(result.dimensions, seriesModel);

        var nameList = createNameList(result, data);

        list.initData(data, nameList);

        return list;
    }

    /**
     * Creaters for each coord system.
     * @return {Object} {dimensions, categoryAxisModel};
     */
    var creaters = {

        cartesian2d: function (data, seriesModel, ecModel) {
            var dimensions = [];
            var categoryAxisModel;
            var xAxisModel = ecModel.getComponent('xAxis', seriesModel.get('xAxisIndex'));
            var yAxisModel = ecModel.getComponent('yAxis', seriesModel.get('yAxisIndex'));
            var xAxisType = xAxisModel.get('type');
            var yAxisType = yAxisModel.get('type');
            var isYAxisCategory = yAxisType === 'category';
            if (xAxisType === 'category') {
                dimensions = [{
                    name: 'x',
                    type: 'ordinal'
                }, {
                    name: 'y',
                    // If two category axes
                    type: isYAxisCategory ? 'ordinal' : 'number',
                    stackable: !isYAxisCategory
                }];

                categoryAxisModel = xAxisModel;
            }
            else if (isYAxisCategory) {
                dimensions = [{
                    name: 'y',
                    type: 'ordinal'
                }, {
                    name: 'x',
                    stackable: true
                }];

                categoryAxisModel = yAxisModel;
            }

            completeDimensions(dimensions, data, ['x', 'y', 'z']);

            return {dimensions: dimensions, categoryAxisModel: categoryAxisModel};
        },

        polar: function (data, seriesModel, ecModel) {
            var dimensions = [];
            var categoryAxisModel;
            var polarIndex = seriesModel.get('polarIndex') || 0;

            var axisFinder = function (axisModel) {
                return axisModel.get('polarIndex') === polarIndex;
            };

            var angleAxisModel = ecModel.findComponents({
                mainType: 'angleAxis', filter: axisFinder
            })[0];
            var radiusAxisModel = ecModel.findComponents({
                mainType: 'radiusAxis', filter: axisFinder
            })[0];

            var isRadiusAxisCategory = radiusAxisModel.get('type') === 'category';
            if (angleAxisModel.get('type') === 'category') {
                dimensions = [{
                    name: 'angle',
                    type: 'ordinal'
                }, {
                    name: 'radius',
                    // If two category axes
                    type: isRadiusAxisCategory ? 'ordinal' : 'number',
                    stackable: !isRadiusAxisCategory
                }];

                categoryAxisModel = angleAxisModel;
            }
            else if (isRadiusAxisCategory) {
                dimensions = [{
                    name: 'radius',
                    type: 'ordinal'
                }, {
                    name: 'angle',
                    stackable: true
                }];

                categoryAxisModel = radiusAxisModel;
            }

            completeDimensions(dimensions, data, ['radius', 'angle', 'value']);

            return {dimensions: dimensions, categoryAxisModel: categoryAxisModel};
        },

        geo: function (data, seriesModel, ecModel) {
            // TODO Region
            // 多个散点图系列在同一个地区的时候
            return {
                dimensions: [
                    {name: 'lng'},
                    {name: 'lat'},
                    {name: 'value'}
                ]
            };
        }
    };

    function createNameList(result, data) {
        var nameList = [];

        if (result.categoryAxisModel) {
            // FIXME Two category axis
            var categories = result.categoryAxisModel.getCategories();
            if (categories) {
                var dataLen = data.length;
                // Ordered data is given explicitly like
                // [[1, 0.2], [2, 0.3], [3, 0.15]]
                // Pick the category
                if (data[0] && data[0].length > 1 && categories.length > dataLen) {
                    nameList = [];
                    for (var i = 0; i < dataLen; i++) {
                        nameList[i] = categories[i];
                    }
                }
                else {
                    nameList = categories.slice(0);
                }
            }
        }

        return nameList;
    }

    return createListFromArray;

});<commit_msg>Use Float64Array default<commit_after>define(function(require) {
    'use strict';

    var List = require('../../data/List');
    var completeDimensions = require('../../data/helper/completeDimensions');

    /**
     * Helper function to create a list from option data
     */
    function createListFromArray(data, seriesModel, ecModel) {
        // If data is undefined
        data = data || [];

        var result = creaters[seriesModel.get('coordinateSystem')](
            data, seriesModel, ecModel
        );

        var list = new List(result.dimensions, seriesModel);

        var nameList = createNameList(result, data);

        list.initData(data, nameList);

        return list;
    }

    /**
     * Creaters for each coord system.
     * @return {Object} {dimensions, categoryAxisModel};
     */
    var creaters = {

        cartesian2d: function (data, seriesModel, ecModel) {
            var dimensions = [];
            var categoryAxisModel;
            var xAxisModel = ecModel.getComponent('xAxis', seriesModel.get('xAxisIndex'));
            var yAxisModel = ecModel.getComponent('yAxis', seriesModel.get('yAxisIndex'));
            var xAxisType = xAxisModel.get('type');
            var yAxisType = yAxisModel.get('type');
            var isYAxisCategory = yAxisType === 'category';
            if (xAxisType === 'category') {
                dimensions = [{
                    name: 'x',
                    type: 'ordinal'
                }, {
                    name: 'y',
                    // If two category axes
                    type: isYAxisCategory ? 'ordinal' : 'float',
                    stackable: !isYAxisCategory
                }];

                categoryAxisModel = xAxisModel;
            }
            else if (isYAxisCategory) {
                dimensions = [{
                    name: 'y',
                    type: 'ordinal'
                }, {
                    name: 'x',
                    stackable: true
                }];

                categoryAxisModel = yAxisModel;
            }

            completeDimensions(dimensions, data, ['x', 'y', 'z']);

            return {dimensions: dimensions, categoryAxisModel: categoryAxisModel};
        },

        polar: function (data, seriesModel, ecModel) {
            var dimensions = [];
            var categoryAxisModel;
            var polarIndex = seriesModel.get('polarIndex') || 0;

            var axisFinder = function (axisModel) {
                return axisModel.get('polarIndex') === polarIndex;
            };

            var angleAxisModel = ecModel.findComponents({
                mainType: 'angleAxis', filter: axisFinder
            })[0];
            var radiusAxisModel = ecModel.findComponents({
                mainType: 'radiusAxis', filter: axisFinder
            })[0];

            var isRadiusAxisCategory = radiusAxisModel.get('type') === 'category';
            if (angleAxisModel.get('type') === 'category') {
                dimensions = [{
                    name: 'angle',
                    type: 'ordinal'
                }, {
                    name: 'radius',
                    // If two category axes
                    type: isRadiusAxisCategory ? 'ordinal' : 'float',
                    stackable: !isRadiusAxisCategory
                }];

                categoryAxisModel = angleAxisModel;
            }
            else if (isRadiusAxisCategory) {
                dimensions = [{
                    name: 'radius',
                    type: 'ordinal'
                }, {
                    name: 'angle',
                    stackable: true
                }];

                categoryAxisModel = radiusAxisModel;
            }

            completeDimensions(dimensions, data, ['radius', 'angle', 'value']);

            return {dimensions: dimensions, categoryAxisModel: categoryAxisModel};
        },

        geo: function (data, seriesModel, ecModel) {
            // TODO Region
            // 多个散点图系列在同一个地区的时候
            return {
                dimensions: [
                    {name: 'lng'},
                    {name: 'lat'},
                    {name: 'value'}
                ]
            };
        }
    };

    function createNameList(result, data) {
        var nameList = [];

        if (result.categoryAxisModel) {
            // FIXME Two category axis
            var categories = result.categoryAxisModel.getCategories();
            if (categories) {
                var dataLen = data.length;
                // Ordered data is given explicitly like
                // [[1, 0.2], [2, 0.3], [3, 0.15]]
                // Pick the category
                if (data[0] && data[0].length > 1 && categories.length > dataLen) {
                    nameList = [];
                    for (var i = 0; i < dataLen; i++) {
                        nameList[i] = categories[i];
                    }
                }
                else {
                    nameList = categories.slice(0);
                }
            }
        }

        return nameList;
    }

    return createListFromArray;

});<|endoftext|>


<commit_before>"use strict";

angular.module("wuw.services")

.factory("Lectures", function($http, $q, Settings) {
    var lectures = JSON.parse(Settings.getSetting('lecturesCache') || '[]');

    var get = function(id) {
        for (var i = 0; i < lectures.length; i++) {
            if (lectures[i]._id === id) {
                return lectures[i];
            }
        }
    };

    var all = function() {
        var deferred = $q.defer();
        $http.get(Settings.getSetting("apiUrl") + "/lectures").
        success(function(data, status, headers, config) {

            // add datefield to every lecutre (used for grouping)
            data.forEach(function(lecture) {
                var d = new Date(lecture.startTime).setHours(0);
                lecture.date = new Date(d).setMinutes(0);
            });
            Settings.setSetting('lecturesCache', JSON.stringify(data));
            Settings.setSetting('lecturesCacheTime', new Date().getTime());
            lectures = data;
            deferred.resolve(data);
        }).
        error(function(data, status, headers, config) {
            deferred.reject(data);
        });
        return deferred.promise;
    };

    var fromCache = function() {
      return lectures;
    };

    var secondsSinceCache = function() {
      var cacheTime = Settings.getSetting('lecturesCacheTime');
      if (typeof cacheTime === 'undefined') {
        return Math.pow(2,32) - 1; // highest integer in JS
      }
      var diff = new Date().getTime() - cacheTime;
      return Math.round(diff / 1000);
    };

    var getCurrentLecture = function() {
      var now = new Date().getTime();
      for (var i = 0; i < lectures.length; i++) {
        var start = new Date(lectures[i].startTime).getTime();
        var end   = new Date(lectures[i].endTime).getTime();
        if (start < now && now < end) {
          return lectures[i];
        }
      }
    };

    var getNextLecture = function() {
      var nextLecture;
      var nextLectureDistance = 18446744073709552000;
      for (var i = 0; i < lectures.length; i++) {
        var lectureDistance = new Date(lectures[i].startTime).getTime();
        if (lectureDistance < nextLectureDistance) {
          nextLectureDistance = lectureDistance;
          nextLecture = lectures[i];
        }
      }
      return nextLecture;
    };

    return {
        lectures: lectures,
        all: all,
        get: get,
        fromCache: fromCache,
        secondsSinceCache: secondsSinceCache,
        getCurrentLecture: getCurrentLecture,
        getNextLecture: getNextLecture
    };
});
<commit_msg>fix getNextLecture(), don't search in the past<commit_after>"use strict";

angular.module("wuw.services")

.factory("Lectures", function($http, $q, Settings) {
    var lectures = JSON.parse(Settings.getSetting('lecturesCache') || '[]');

    var get = function(id) {
        for (var i = 0; i < lectures.length; i++) {
            if (lectures[i]._id === id) {
                return lectures[i];
            }
        }
    };

    var all = function() {
        var deferred = $q.defer();
        $http.get(Settings.getSetting("apiUrl") + "/lectures").
        success(function(data, status, headers, config) {

            // add datefield to every lecutre (used for grouping)
            data.forEach(function(lecture) {
                var d = new Date(lecture.startTime).setHours(0);
                lecture.date = new Date(d).setMinutes(0);
            });
            Settings.setSetting('lecturesCache', JSON.stringify(data));
            Settings.setSetting('lecturesCacheTime', new Date().getTime());
            lectures = data;
            deferred.resolve(data);
        }).
        error(function(data, status, headers, config) {
            deferred.reject(data);
        });
        return deferred.promise;
    };

    var fromCache = function() {
      return lectures;
    };

    var secondsSinceCache = function() {
      var cacheTime = Settings.getSetting('lecturesCacheTime');
      if (typeof cacheTime === 'undefined') {
        return Math.pow(2,32) - 1; // highest integer in JS
      }
      var diff = new Date().getTime() - cacheTime;
      return Math.round(diff / 1000);
    };

    var getCurrentLecture = function() {
      var now = new Date().getTime();
      for (var i = 0; i < lectures.length; i++) {
        var start = new Date(lectures[i].startTime).getTime();
        var end   = new Date(lectures[i].endTime).getTime();
        if (start < now && now < end) {
          return lectures[i];
        }
      }
    };

    var getNextLecture = function() {
      var nextLecture;
      var nextLectureDistance = 18446744073709552000;
      for (var i = 0; i < lectures.length; i++) {
        var lectureDistance = new Date(lectures[i].startTime).getTime() - new Date().getTime();
        if (lectureDistance < nextLectureDistance && lectureDistance > 0) {
          nextLectureDistance = lectureDistance;
          nextLecture = lectures[i];
        }
      }
      return nextLecture;
    };

    return {
        lectures: lectures,
        all: all,
        get: get,
        fromCache: fromCache,
        secondsSinceCache: secondsSinceCache,
        getCurrentLecture: getCurrentLecture,
        getNextLecture: getNextLecture
    };
});
<|endoftext|>


<commit_before>"use strict";
var MapController = function($location, $scope, $timeout, analytics, config, mapTooltipFactory, navigation) {

	var MIN_TIME_BETWEEN_UPDATES = 100; // .1 seconds

	var socket = null;
	var defaultMarker = null;
	var hoverMarker = null;

	var activeMarker = null;
	var lastMarkerUpdateTime = null;
	var mapStabilized = false;
	var showBanner = false;
	var doneShowingBanner = false;
	var formattedLocationString = null;
	var searchQuery = null;
	var center = null;
	var zoomLevel = 0;

	$scope.mapOptions = null;
	$scope.markers = [];

	var initIcons = function() {
		defaultMarker = {
			path: google.maps.SymbolPath.CIRCLE,
			fillOpacity: 1,
			fillColor: "#EB593C",
			strokeWeight: 1.0,
			scale: 4
		};
		hoverMarker = {
			path: google.maps.SymbolPath.CIRCLE,
			fillOpacity: 1,
			fillColor: "#FFFF33",
			strokeWeight: 1.0,
			scale: 5
		};
	};

	var initMapOptions = function() {
		updateViewport($location.search());
		$scope.mapOptions = {
			zoom: zoomLevel,
			center: center,
			mapTypeId: google.maps.MapTypeId.TERRAIN
		};
	};

	var initSocketIo = function() {
		socket = io.connect(config.socketIoPath);
		socket.on("get-hikes-in-bounds", incomingSocketDataArrived);
	};

	var deactivateMarker = function(marker) {
		var tooltip = marker.tooltips.pop();
		if (tooltip) {
			tooltip.destroy();
		}
		if (marker.tooltips.length === 0) {
			marker.setIcon(defaultMarker);
		}
	};

	var activateMarker = function(marker) {
		if (activeMarker && activeMarker !== marker) {
			deactivateMarker(activeMarker);
			activeMarker = null;
		}
		var tooltip = mapTooltipFactory.create(marker);
		marker.tooltips.push(tooltip);
		marker.setIcon(hoverMarker);
		activeMarker = marker;
	};

	var updateViewportToDefault = function() {
		if (google.loader.ClientLocation) {
			var clientLocation = google.loader.ClientLocation;
			center = new google.maps.LatLng(clientLocation.latitude, clientLocation.longitude);
			zoomLevel = 5;
		} else {
			// Default to a central view of the US
			center = new google.maps.LatLng(15, -90); // Center over the Americas since they have the most hikes currently.
			zoomLevel = 3;
		}
	};

	var updateViewportFromUrlParams = function(urlParams) {
		formattedLocationString = urlParams.address;
		searchQuery = urlParams.q;

		if (urlParams.lat && urlParams.lng) {
			center = new google.maps.LatLng(parseFloat(urlParams.lat), parseFloat(urlParams.lng));
			zoomLevel = parseInt(urlParams.zoom, 10) || 11;
		}

		if (searchQuery) {
			$scope.bannerString = "Unable to find location " + searchQuery;
			showBanner = true;
		}
		console.log("Updating viewport ");
		console.log(urlParams);
	};

	var updateViewport = function(urlParams) {
		updateViewportFromUrlParams(urlParams);
		if (!center) {
			updateViewportToDefault();
		}
	};

	var incomingSocketDataArrived = function(data) {
		$scope.$apply(function() {
			if (data.length === 0) {
				console.log(formattedLocationString, doneShowingBanner, showBanner);
				if (formattedLocationString && !doneShowingBanner) {
					$scope.bannerString = "Unable to find hikes near " + formattedLocationString + ". Try zooming out.";
					showBanner = true;
				}
			}
			mergeMarkers(data);
		});
	};

	var compareLatLng = function(a, b) {
		if		(a.lat() < b.lat())		{	return -1;	}
		else if (a.lat() > b.lat())		{	return 1;	}
		else if (a.lng() < b.lng())		{	return -1;	}
		else if (a.lng() > b.lng())		{	return 1;	}
		else							{	return 0;	}
	};

	var mergeMarkers = function(newMarkers) {
		var i = 0;
		var j = 0;
		var mergedMarkers = [];
		while (i !== newMarkers.length || j !== $scope.markers.length) {
			var newLatLng = null;
			var oldMarker = null;
			var oldLatLng = null;

			if (i < newMarkers.length) {
				newLatLng = new google.maps.LatLng(newMarkers[i].latitude, newMarkers[i].longitude);
			}

			if (j < $scope.markers.length) {
				oldMarker = $scope.markers[j];
				oldLatLng = oldMarker.getPosition();
			}

			if (!oldLatLng || (newLatLng && compareLatLng(newLatLng, oldLatLng) < 0)) {
				// This is a brand new marker, add it
				var marker = new google.maps.Marker({
					icon: defaultMarker,
					map: $scope.map,
					position: newLatLng,
					hikeData: newMarkers[i],
					tooltips: []
				});
				mergedMarkers.push(marker);
				i++;
			} else if (!newLatLng || (oldLatLng && compareLatLng(newLatLng, oldLatLng) > 0)) {
				// The old marker is no longer in use, remove it
				oldMarker.setMap(null);
				j++;
			} else {
				// Use the existing marker
				mergedMarkers.push(oldMarker);
				i++;
				j++;
			}
		}
		$scope.markers = mergedMarkers;
	};

	$scope.$on("resetMapViewport", function(event, urlParams) {
		console.log("Resetting viewport");
		if (activeMarker) {
			deactivateMarker(activeMarker);
			activeMarker = null;
		}
		center = null;
		zoomLevel = 0;
		doneShowingBanner = false;
		showBanner = false;
		mapStabilized = false;
		formattedLocationString = null;
		searchQuery = null;
		lastMarkerUpdateTime = null;

		updateViewport(urlParams);
		$scope.map.setCenter(center);
		$scope.map.setZoom(zoomLevel);
	});

	$scope.markerMousedOver = function(marker) {
		activateMarker(marker);
	};

	$scope.markerMousedOut = function(marker) {
		$timeout(function() {
			deactivateMarker(marker);
		}, 300);
	};

	$scope.markerClicked = function(marker) {
		if (Modernizr.touch && marker !== activeMarker) {
			activateMarker(marker);
			// Link to the entry will be on the tooltip itself.
		} else {
			navigation.toEntry(marker.hikeData.string_id);
		}
	};

	$scope.mapMoved = function(event) {
		if (lastMarkerUpdateTime &&
				event.type !== "map-idle" &&
				event.timestamp - lastMarkerUpdateTime < MIN_TIME_BETWEEN_UPDATES) {
			// Recently updated, ignore this update request
			return;
		}
		lastMarkerUpdateTime = event.timestamp;

		var bounds = $scope.map.getBounds();
		var center = $scope.map.getCenter();
		var zoomLevel = $scope.map.getZoom();

		var northEast = bounds.getNorthEast();
		var northEastLatLng = {
			latitude: northEast.lat(),
			longitude: northEast.lng()
		};
		var southWest = bounds.getSouthWest();
		var southWestLatLng = {
			latitude: southWest.lat(),
			longitude: southWest.lng()
		};
		console.log(event.type, mapStabilized, showBanner, doneShowingBanner);
		if (event.type !== "map-idle" && mapStabilized) {
			console.log("Map moving, stop showing banner");
			showBanner = false; // Map is being moved, hide banner
			doneShowingBanner = true;
			mapStabilized = false;
		}
		if (event.type === "map-idle") {
			mapStabilized = true;
			$location.search({lat: center.lat().toFixed(3), lng: center.lng().toFixed(3), zoom: zoomLevel}).replace();
		}
		socket.emit("get-hikes-in-bounds", { ne: northEastLatLng, sw: southWestLatLng });
	};

	// Init
	initIcons();
	initMapOptions();
	initSocketIo();
	$scope.htmlReady();
};

MapController.$inject = ["$location", "$scope", "$timeout", "analytics", "config", "mapTooltipFactory", "navigation"];<commit_msg>Variable showBanner should be on the scope.<commit_after>"use strict";
var MapController = function($location, $scope, $timeout, analytics, config, mapTooltipFactory, navigation) {

	var MIN_TIME_BETWEEN_UPDATES = 100; // .1 seconds

	var socket = null;
	var defaultMarker = null;
	var hoverMarker = null;

	var activeMarker = null;
	var lastMarkerUpdateTime = null;
	var mapStabilized = false;
	var doneShowingBanner = false;
	var formattedLocationString = null;
	var searchQuery = null;
	var center = null;
	var zoomLevel = 0;

	$scope.mapOptions = null;
	$scope.markers = [];
	$scope.bannerString = null;
	$scope.showBanner = false;

	var initIcons = function() {
		defaultMarker = {
			path: google.maps.SymbolPath.CIRCLE,
			fillOpacity: 1,
			fillColor: "#EB593C",
			strokeWeight: 1.0,
			scale: 4
		};
		hoverMarker = {
			path: google.maps.SymbolPath.CIRCLE,
			fillOpacity: 1,
			fillColor: "#FFFF33",
			strokeWeight: 1.0,
			scale: 5
		};
	};

	var initMapOptions = function() {
		updateViewport($location.search());
		$scope.mapOptions = {
			zoom: zoomLevel,
			center: center,
			mapTypeId: google.maps.MapTypeId.TERRAIN
		};
	};

	var initSocketIo = function() {
		socket = io.connect(config.socketIoPath);
		socket.on("get-hikes-in-bounds", incomingSocketDataArrived);
	};

	var deactivateMarker = function(marker) {
		var tooltip = marker.tooltips.pop();
		if (tooltip) {
			tooltip.destroy();
		}
		if (marker.tooltips.length === 0) {
			marker.setIcon(defaultMarker);
		}
	};

	var activateMarker = function(marker) {
		if (activeMarker && activeMarker !== marker) {
			deactivateMarker(activeMarker);
			activeMarker = null;
		}
		var tooltip = mapTooltipFactory.create(marker);
		marker.tooltips.push(tooltip);
		marker.setIcon(hoverMarker);
		activeMarker = marker;
	};

	var updateViewportToDefault = function() {
		if (google.loader.ClientLocation) {
			var clientLocation = google.loader.ClientLocation;
			center = new google.maps.LatLng(clientLocation.latitude, clientLocation.longitude);
			zoomLevel = 5;
		} else {
			// Default to a central view of the US
			center = new google.maps.LatLng(15, -90); // Center over the Americas since they have the most hikes currently.
			zoomLevel = 3;
		}
	};

	var updateViewportFromUrlParams = function(urlParams) {
		formattedLocationString = urlParams.address;
		searchQuery = urlParams.q;

		if (urlParams.lat && urlParams.lng) {
			center = new google.maps.LatLng(parseFloat(urlParams.lat), parseFloat(urlParams.lng));
			zoomLevel = parseInt(urlParams.zoom, 10) || 11;
		}

		if (searchQuery) {
			$scope.bannerString = "Unable to find location " + searchQuery;
			$scope.showBanner = true;
		}
		console.log("Updating viewport ");
		console.log(urlParams);
	};

	var updateViewport = function(urlParams) {
		updateViewportFromUrlParams(urlParams);
		if (!center) {
			updateViewportToDefault();
		}
	};

	var incomingSocketDataArrived = function(data) {
		$scope.$apply(function() {
			if (data.length === 0) {
				console.log(formattedLocationString, doneShowingBanner, $scope.showBanner);
				if (formattedLocationString && !doneShowingBanner) {
					$scope.bannerString = "Unable to find hikes near " + formattedLocationString + ". Try zooming out.";
					$scope.showBanner = true;
				}
			}
			mergeMarkers(data);
		});
	};

	var compareLatLng = function(a, b) {
		if		(a.lat() < b.lat())		{	return -1;	}
		else if (a.lat() > b.lat())		{	return 1;	}
		else if (a.lng() < b.lng())		{	return -1;	}
		else if (a.lng() > b.lng())		{	return 1;	}
		else							{	return 0;	}
	};

	var mergeMarkers = function(newMarkers) {
		var i = 0;
		var j = 0;
		var mergedMarkers = [];
		while (i !== newMarkers.length || j !== $scope.markers.length) {
			var newLatLng = null;
			var oldMarker = null;
			var oldLatLng = null;

			if (i < newMarkers.length) {
				newLatLng = new google.maps.LatLng(newMarkers[i].latitude, newMarkers[i].longitude);
			}

			if (j < $scope.markers.length) {
				oldMarker = $scope.markers[j];
				oldLatLng = oldMarker.getPosition();
			}

			if (!oldLatLng || (newLatLng && compareLatLng(newLatLng, oldLatLng) < 0)) {
				// This is a brand new marker, add it
				var marker = new google.maps.Marker({
					icon: defaultMarker,
					map: $scope.map,
					position: newLatLng,
					hikeData: newMarkers[i],
					tooltips: []
				});
				mergedMarkers.push(marker);
				i++;
			} else if (!newLatLng || (oldLatLng && compareLatLng(newLatLng, oldLatLng) > 0)) {
				// The old marker is no longer in use, remove it
				oldMarker.setMap(null);
				j++;
			} else {
				// Use the existing marker
				mergedMarkers.push(oldMarker);
				i++;
				j++;
			}
		}
		$scope.markers = mergedMarkers;
	};

	$scope.$on("resetMapViewport", function(event, urlParams) {
		console.log("Resetting viewport");
		if (activeMarker) {
			deactivateMarker(activeMarker);
			activeMarker = null;
		}
		center = null;
		zoomLevel = 0;
		doneShowingBanner = false;
		$scope.showBanner = false;
		mapStabilized = false;
		formattedLocationString = null;
		searchQuery = null;
		lastMarkerUpdateTime = null;

		updateViewport(urlParams);
		$scope.map.setCenter(center);
		$scope.map.setZoom(zoomLevel);
	});

	$scope.markerMousedOver = function(marker) {
		activateMarker(marker);
	};

	$scope.markerMousedOut = function(marker) {
		$timeout(function() {
			deactivateMarker(marker);
		}, 300);
	};

	$scope.markerClicked = function(marker) {
		if (Modernizr.touch && marker !== activeMarker) {
			activateMarker(marker);
			// Link to the entry will be on the tooltip itself.
		} else {
			navigation.toEntry(marker.hikeData.string_id);
		}
	};

	$scope.mapMoved = function(event) {
		if (lastMarkerUpdateTime &&
				event.type !== "map-idle" &&
				event.timestamp - lastMarkerUpdateTime < MIN_TIME_BETWEEN_UPDATES) {
			// Recently updated, ignore this update request
			return;
		}
		lastMarkerUpdateTime = event.timestamp;

		var bounds = $scope.map.getBounds();
		var center = $scope.map.getCenter();
		var zoomLevel = $scope.map.getZoom();

		var northEast = bounds.getNorthEast();
		var northEastLatLng = {
			latitude: northEast.lat(),
			longitude: northEast.lng()
		};
		var southWest = bounds.getSouthWest();
		var southWestLatLng = {
			latitude: southWest.lat(),
			longitude: southWest.lng()
		};
		console.log(event.type, mapStabilized, $scope.showBanner, doneShowingBanner);
		if (event.type !== "map-idle" && mapStabilized) {
			console.log("Map moving, stop showing banner");
			$scope.showBanner = false; // Map is being moved, hide banner
			doneShowingBanner = true;
			mapStabilized = false;
		}
		if (event.type === "map-idle") {
			mapStabilized = true;
			$location.search({lat: center.lat().toFixed(3), lng: center.lng().toFixed(3), zoom: zoomLevel}).replace();
		}
		socket.emit("get-hikes-in-bounds", { ne: northEastLatLng, sw: southWestLatLng });
	};

	// Init
	initIcons();
	initMapOptions();
	initSocketIo();
	$scope.htmlReady();
};

MapController.$inject = ["$location", "$scope", "$timeout", "analytics", "config", "mapTooltipFactory", "navigation"];<|endoftext|>