



// This must be in the global namespace, so that the tinyMCE editor can access it.
function onTinyMCEEditorChanged() {
    if( tinyMCE.activeEditor.isDirty() ) {
        // The "onTextAreaChanged" attribute is set in the ready()-function.
        onTinyMCEEditorChanged.onTextAreaChanged();
    }
}



// Create a namespace for the various functions and variables in this file. 
// TODO: move (almost) everything into this function. (Now most of the function is declared locally
//       in the call to $(document).ready(function()), which doesn't feel right.
var PROSJEKT_EDIT_VIEW = {

    initialize : function() {
            // The currently selected language.
        PROSJEKT_EDIT_VIEW.language = $("#languageholder").attr("class");
        var portalurlholder = $("#portalurlholder");
        PROSJEKT_EDIT_VIEW.portalURL = portalurlholder.text();
        PROSJEKT_EDIT_VIEW.formPostURL = $("div.addnewwindow form").attr("action"); // All the person-edit forms post to the same url, so we can store it here
        
        $("body").ajaxStart(PROSJEKT_EDIT_VIEW.onAjaxStart);
        $("body").ajaxStop( PROSJEKT_EDIT_VIEW.onAjaxStop);        

        // Intercept "Enter" keystrokes on the body-tag, otherwise IE6 will open up one of the Calendar widgets, for some reason.
        $("body").keydown(function(event) {
                if(event.which == 13 ) {
                    event.preventDefault();
                    return false;
                }
            });

        
        
    }

    /* Zope doesn't like us to send several ajax-requests simultaneously (we often get database conflict errors),
       so we use a message-queue to ensure that we only have one active ajax call at a time. This is transparant
       to the rest of the code (which just uses the postJSON() method) */
    ,postJSONQueue : new Array()
    ,anAjaxRequestIsPending : false
    
    // this is run whenever an AJAX request begins and there is none already active
    ,onAjaxStart : function() {
        PROSJEKT_EDIT_VIEW.anAjaxRequestIsPending = true;
        
        // disable all "Close" buttons, since it is confusing for the user to be able to
        // close a searchwindow and then have pending ajax-requests that were triggered from
        // that searchwindow complete later. We also disable the "Search"-buttons for similar
        // reasons.
        $("div.searchwindow button.close").attr("disabled","disabled");
        $("div.searchwindow button.search").attr("disabled","disabled");
    }
    // this is run whenever all AJAX requests have ended
    ,onAjaxStop : function() {
        // Check if there are any more pending ajax-requests in the queue. If it is we send
        // the next one.
        if( PROSJEKT_EDIT_VIEW.postJSONQueue.length > 0 ) {
            ajaxparams = PROSJEKT_EDIT_VIEW.postJSONQueue.shift();
            jQuery.ajax(ajaxparams);
        } else {
            PROSJEKT_EDIT_VIEW.anAjaxRequestIsPending = false;
            $("div.searchwindow button.close").removeAttr("disabled");
            $("div.searchwindow button.search").removeAttr("disabled");            
        }
    }

    ,postJSON : function (options) {    
        options = jQuery.extend( { 'type': 'POST'
                                 , 'contentType': 'application/json'
                                 , 'processData': false 
                                 , 'timeout': 60000
                                 , 'dataType': 'json'
                                 }
                               , options);
        options.data = JSON.stringify(options.data);
        options._error = options.error
        options.error = function (event) {
            //TODO: Handle other HTTP error codes like redirect.
            //console.log('errorhandler');
            if (event.readyState === 0) {
                // Timeout
                //console.log('Timeout', event);
                if (options.timeoutError)
                    options.timeoutError(event);
                else if (options._error)
                    options._error(event);
            } else if (event.status === 0) {
                //console.log('No answer', event);
                if (options.noreplyError) 
                    options.noreplyError(event);
                else if (options._error)
                    options._error(event);
            } else if (event.status === 404) {
                // Topic has been deleted
                //console.log('404', event);
                humanMsg.displayMsg("Error: The page wasn't found.");
            } else if (event.status >= 500) {
                //console.log('error', event, options._error);
                if (options._error)
                    options._error(event);
            } else {
                //console.log('errorhandler  got an unknown error!', event, options._error);
                if (options._error)
                    options._error(event);
            }
            return false;
        };
        
        //TODO: Support difference between TIMEOUT, UNREACHABLE and SERVER ERROR
        //TODO: Use object literal as input.
        
        // Append the options to the ajax-queue
        PROSJEKT_EDIT_VIEW.postJSONQueue.push(options);
        // If no ajax-call is currently pending, send the request at once. (Otherwise the
        // request will be sent by PROSJEKT_EDIT_VIEW.onAjaxStop()
        if( ! PROSJEKT_EDIT_VIEW.anAjaxRequestIsPending ) {
            options = PROSJEKT_EDIT_VIEW.postJSONQueue.shift(); 
            jQuery.ajax(options);
        }

    }

    //utility-function for hiding or showing the associationcontrols if needed. 
    ,hideOrShowAssocControlsIfNeeded : function(ulElement) {
        var divElement = ulElement.parent();
        var limit = -1;
        
        // Figure out which kind of association this is.
        if( divElement.hasClass("selecteddocuments") ) {
            /* no limit.*/
            limit = -1;
        }
        
        if( divElement.hasClass("utvalgte_publikasjoner") ) {
            /* no limit.*/
            limit = -1;
        }
        
        if( limit >= 0 ) {
            var associationcontrols    = $("div.associationcontrols",divElement);
            // The user shouldn't add more than a certain number of this association, so we must hide the associationcontrols if the
            // limit is reached.
            if( $("li",ulElement).length >= 20 ) {
                // Too many associations, so hide the assoc-controls.
                // make sure the search-window is closed, by simulating
                // a mouseclick in the "close" button.
                $("div.searchwindow button.close", divElement).click();
                //$("div.addnewwindow button.cancel", divElement).click();
                
                associationcontrols.slideUp(1000);
            } else {
                // There are not too many associations, so show the assoc-controls.
                associationcontrols.slideDown(1000);
            }
        }
    }
    
    ,onVisAvsluttedeProsjekterClicked : function(event) {
        $("div.visavsluttedeprosjekter").slideUp(1000);
        $("div.avsluttedeprosjekter").slideDown(1000,  
                 SET_MIDDLE_COLUMN_HEIGHTS.equalHeight // Trigger the equalHeight()-function in the "setmiddlecolheights.js" script, so that the 
                                                       // left and right columns gets resized.
            );
    
        event.preventDefault();
        return false;
    }
    
    ,onSkjulAvsluttedeProsjekterClicked : function(event) {
        $("div.avsluttedeprosjekter").slideUp(1000);
        $("div.visavsluttedeprosjekter").slideDown(1000,  
                 SET_MIDDLE_COLUMN_HEIGHTS.equalHeight // Trigger the equalHeight()-function in the "setmiddlecolheights.js" script, so that the 
                                                       // left and right columns gets resized.
            );
        event.preventDefault();
        return false;
    }



    ,onShowAdditionalImagesClicked : function(event) {
        $("div.showadditionalimages").slideUp(1000);
        $("div.additionalimages").slideDown(1000);
        event.preventDefault();
        return false;
    }
    
    ,onHideAdditionalImagesClicked : function(event) {
        $("div.showadditionalimages").slideDown(1000);
        $("div.additionalimages").slideUp(1000);
        event.preventDefault();
        return false;
    }


    ,onOpenReplaceWindowClicked : function(event) {
        var button = $(event.target);
        var liElement = button.parents("li").get(0);
        var replacewindow = $("div.replacewindow",liElement);
        replacewindow.slideDown(1000);
        button.attr("disabled","disabled");
        event.preventDefault();
        return false;
    }
    
    ,onCloseReplaceWindowClicked : function(event) {
        var button = $(event.target);
        var liElement = button.parents("li").get(0);
        var replacewindow = $("div.replacewindow",liElement);
        replacewindow.slideUp(1000);
        $("button.openreplacewindow",liElement).removeAttr("disabled");
        event.preventDefault();
        return false;
    }


    ,addEditFormHandlers : function(liElement) {
        var openEditWindowButton = $("button.openeditwindow",liElement);
        if( openEditWindowButton == undefined ) {
            // This element didn't have an editwindow. This is normal.
            return;
        }
        
        var editWindow = $("div.editwindow",liElement);
        var closeEditWindowButton = $("button.cancel",editWindow);
        var saveButton = $("button.save",editWindow);
        var editWindow_bottom = $(".editwindow_bottom",editWindow);
        
        /***********************************************************************************************/
        // Handlers for the "edit publication" controls.
        /***********************************************************************************************/
        function onopenEditWindowButton(event) {
            //$.scrollTo("+=200px",500);
            editWindow.slideDown(500, function() 
                {
              //      $.scrollTo(editWindow_bottom,500);
                });
            
            if( $.browser.msie ) {
                // IE doesn't display the text-controls if we just try to do a fancy animation. It seems to 
                // work to toggle the visibility on and off, though.
                window.setTimeout(function() {
                                            editWindow.hide();
                                            editWindow.show();
                                            },
                                            600);
            } 
                
        }
        openEditWindowButton.click(onopenEditWindowButton);
        
        function onCloseEditWindowButton(event) {
            openEditWindowButton.removeAttr("disabled");
            editWindow.slideUp(1000);
        }
        closeEditWindowButton.click(onCloseEditWindowButton);    
        
        function onSaveTopicButton(event) {        
            // Disable the save-button, so that the user cannot spam the server by clicking
            // it repeatedly. TODO: make this function generic, so that we don't have to hardcode
            // the list of form-values.
            saveButton.attr("disabled","disabled");
            
            var titleTextCtrl            = $("input.title",editWindow);
            var publikasjonsnavnTextCtrl = $("input.publikasjonsnavn",editWindow);
            var urlTextCtrl              = $("input.url",editWindow);
            var topicserialTextCtrl      = $("input.topicserial",editWindow);
                
            var data = {'language':PROSJEKT_EDIT_VIEW.language,
                        'operation': 'updatepublication',
                        'title':titleTextCtrl.val(),
                        'url':urlTextCtrl.val(),
                        'publikasjonsnavn':publikasjonsnavnTextCtrl.val(),
                        'topicserial':topicserialTextCtrl.val()
                        }
            
            var loadingimg = saveButton.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 // success, so update the gui with the new values. 
                                                 var newtext = response['newtext'];
                                                 var newurl  = response['newurl'];
                                                 var linkElement = $("a.publikasjonslenke",liElement);
                                                 linkElement.children("span").html(newtext);
                                                 linkElement.attr("href",newurl);
                                                 
                                                 if(newurl != '' ) {
                                                    if( linkElement.hasClass("tompublikasjonslenke")) {
                                                        linkElement.removeClass("tompublikasjonslenke");
                                                    }
                                                 } else {
                                                    if( ! linkElement.hasClass("tompublikasjonslenke")) {
                                                        linkElement.addClass("tompublikasjonslenke");
                                                    }
                                                 }
                                                 
                                                 saveButton.removeAttr("disabled");
                                                 onCloseEditWindowButton();                                             
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                saveButton.removeAttr("disabled");
                                                humanMsg.displayMsg("Failed to update the topic!"); 
                                                }
                    });


        }
        saveButton.click(onSaveTopicButton);        
    }
    
    ,addUploadFormHandlers:function(openAddNewWindowButton,addnewWindow,searchandaddbuttonsbar,openSearchWindowButton) {
        var documentUploadButton = $("button.documentUploadbutton",addnewWindow);
        
        
        
        var loadingimg;
        if(searchandaddbuttonsbar!=undefined) {
            loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
        } else {
            searchandaddbuttonsbar = $("<span/>"); // Make a dummy element so we don't have to test searchandaddbuttonsbar!=undefined everywhere
            loadingimg = openAddNewWindowButton.siblings().filter(".loadingimg");
        }
    
        if( openSearchWindowButton == undefined ) {
            openSearchWindowButton = $("<span/>"); // Make a dummy element so we don't have to test searchandaddbuttonsbar!=undefined everywhere
        }
        
        function onBrowseCtrlChanged(event)
        {
            // Enable the upload button
            documentUploadButton.removeAttr("disabled");
        }
        
        
        function onOpenAddNewWindowButton(event) {
            var documentFileToUpload = $("input.documentFileToUpload",addnewWindow);
            documentFileToUpload.val("");
            var titleInput = $("input.title",addnewWindow);
            titleInput.val("");
            var descriptionInput = $("textarea.description",addnewWindow);
            descriptionInput.val("");
            // disable the upload-button. It will be enabled once the user selects a file.
            documentUploadButton.attr("disabled","disabled");
            searchandaddbuttonsbar.slideUp(500);
            
            //$.scrollTo("+=200px",500);
            addnewWindow.slideDown(500);//, function() {$.scrollTo(addnewWindow_bottom,500);} );
            documentFileToUpload.change(onBrowseCtrlChanged);
        }
        openAddNewWindowButton.click(onOpenAddNewWindowButton);
        
        function onCloseAddNewWindowButtonClicked(event) {
            if( event != undefined ) {
                event.preventDefault();
            }
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            addnewWindow.slideUp(1000);
        }
        closeAddNewWindowButton = $("button.cancel",addnewWindow);
        closeAddNewWindowButton.click(onCloseAddNewWindowButtonClicked);    

        // Handlers for the file-uploading of new documents.
        // We must override the function in ajaxfileupload, since Zope insists on adding bogus  <pre>-tags around the json data.
        function myUploadHttpData( r, type ) {
                var data = !type;
                data = type == "xml" || data ? r.responseXML : r.responseText;
                if( type == "raw" ) {
                    data = r.responseText;
                }
                // If the type is "script", eval it in global context
                if ( type == "script" )
                    jQuery.globalEval( data );
                // Get the JavaScript object, if JSON is used.
                if ( type == "json" ) {
                    // knutj09july2008: Hack to get fileuploading to work. Zope seems to add <pre>-tags around the json-data, for some reason.
                    if(data.length >= 10 ) {
                        // Check for bogus <pre>-tags added by zope
                        if( data.indexOf("<pre>") == 0 ) {
                            if( data.substr(data.length-6) == "</pre>" ) {
                                data = data.substring(5,data.length-6);
                            }
                        }
                    }
                    eval( "data = " + data );
                    }
                // evaluate scripts within html
                if ( type == "html" )
                    jQuery("<div>").html(data).evalScripts();
                    //alert($('param', data).each(function(){alert($(this).attr('value'));}));
                return data;
        }
        

        
        function ajaxFileUpload()
        {   

            var documentFileToUpload = $("input.documentFileToUpload",addnewWindow);
            loadingimg.show();
            
            // We must override the function in ajaxfileupload, since Zope insists on adding bogus  <pre>-tags around the json data.
            var oldUploadHttpData = jQuery.uploadHttpData;
            jQuery.uploadHttpData = myUploadHttpData;

            // We must override the "createUploadForm"-function in ajaxfileupload, since we need to
            // add the language and title as an input-field in the form.
            var oldCreateUploadForm = jQuery.createUploadForm;
            jQuery.createUploadForm =  function (id, fileElementId){
                var form = oldCreateUploadForm(id,fileElementId);
                var language = $("#languageholder").attr("class");
                form.append('<input type="hidden" name="language" value="' + language + '" >');
            
                var topicserial = addnewWindow.attr("ztm:topicserial");
                if( topicserial ) {
                    form.append('<input type="hidden" name="filetoreplace" value="' + topicserial + '" >');
                }
                
                var originalForm = $("#" + fileElementId).parents("form:first");
                var titleInput = $("input.title",originalForm);
                if( titleInput ) {
                    var title = titleInput.val();
                    form.append('<input type="hidden" name="title" value="' + title + '" >');
                }
                var descriptionInput = $("textarea.description",originalForm);
                if( descriptionInput ) {
                    var description = descriptionInput.val();
                    form.append('<textarea type="hidden" name="description">' + description + '</textarea>');
                }
                
                return form;
                };
        
            // temporarily disable the upload-button, so that the user cannot spam the server by clicking it 
            // repeatedly
            documentUploadButton.attr("disabled","disabled");
            
            /*
                preparing ajax file upload
                url: the url of script file handling the uploaded files
                            fileElementId: the file type of input element id and it will be the index of  $_FILES Array()
                dataType: it support json, xml
                secureuri:use secure protocol
                success: call back function when the ajax complete
                error: callback function when the ajax failed
                
                    */
            var ajavFileUploadParams =  {
                    url : PROSJEKT_EDIT_VIEW.formPostURL, 
                    secureuri:false,
                    fileElementId:documentFileToUpload.attr("id"),
                    dataType: 'raw',
                    success: function (data, status)
                    {
                        jQuery.uploadHttpData = oldUploadHttpData;
                        jQuery.createUploadForm = oldCreateUploadForm;
                        loadingimg.hide();
                        documentUploadButton.removeAttr("disabled");
                        // the new line is returned as a raw html-string (for some reason it doesn't work to return
                        // json-data), so we must fake a response that the updateSelectedDocumentList() function understands.
                        PROSJEKT_EDIT_VIEW.updateSelectedDocumentList({'newline':data});
                        onCloseAddNewWindowButtonClicked(undefined);
                    },
                    error: function (data, status, e)
                    {
                        jQuery.uploadHttpData = oldUploadHttpData;
                        jQuery.createUploadForm = oldCreateUploadForm;
                        loadingimg.hide();
                        documentUploadButton.removeAttr("disabled");
                        humanMsg.displayMsg("Failed to upload the file!");
                        alert(e);
                    }
                };
                
            $.ajaxFileUpload(ajavFileUploadParams);                
            return false;
        }  
        
        
        documentUploadButton.click(ajaxFileUpload)
    }
    
    
    
    , updateSelectedDocumentList : function(response) {
        var selecteddocuments = $("div.selecteddocuments");
        var ulElement = $("ul.selecteddocuments",selecteddocuments);
        var newline = response['newline'];
        if( newline ) {
            newline = $(newline);
            ulElement.append(newline);      
            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(newline);
            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
        }
    }


    ,setEvenAndOddClasses : function(ulElement) {
        ulElement.children().each(function(index,liElement) {
            liElement = $(liElement);
            if( index % 2 ) {
                liElement.removeClass("even").addClass("odd");
            } else {
                liElement.removeClass("odd").addClass("even");
            }
        });
    }


    /***********************************************************************************************/
    // Utility-function for applying the handlers to each "li"-element. This function is also required in order
    // to re-apply the eventhandlers when a li-element is moved.
    /***********************************************************************************************/
    ,addPublicationOrDocumentLineHandlers : function(liElement) {
        var liElement = $(liElement);
        var isDocumentLine = liElement.hasClass("selecteddocument");
        
        var associationMoveUpButton = $(".associationmoveupbutton",liElement);
        associationMoveUpButton.click(PROSJEKT_EDIT_VIEW.onAssociationMoveupButton);
        var prevElement = liElement.prev("li");
        if(prevElement.length == 0){
            associationMoveUpButton.attr("disabled","disabled");
        } else {
            associationMoveUpButton.removeAttr("disabled");
        }
        
        var associationMoveDownButton = $(".associationmovedownbutton",liElement);
        associationMoveDownButton.click(PROSJEKT_EDIT_VIEW.onAssociationMovedownButton);
        var nextElement = liElement.next("li");
        if(nextElement.length == 0){
            associationMoveDownButton.attr("disabled","disabled");
        } else {
            associationMoveDownButton.removeAttr("disabled");
        }
        
        var associationDeleteButton = $(".associationdeletebutton",liElement);
        associationDeleteButton.click(PROSJEKT_EDIT_VIEW.onAssociationDeleteButton);
        
        var languagecheckboxes = $("input.languagecheckbox",liElement);
        if( isDocumentLine ) {
            languagecheckboxes.click(PROSJEKT_EDIT_VIEW.onExclusiveLanguageCheckBox);
        } else {
            languagecheckboxes.click(PROSJEKT_EDIT_VIEW.onLanguageCheckBox);
        }
        
        var openreplacewindowbutton = $("button.openreplacewindow",liElement);
        if( openreplacewindowbutton != undefined ) {
            var replacewindow = $("div.replacewindow",liElement);
            PROSJEKT_EDIT_VIEW.addUploadFormHandlers(openreplacewindowbutton,replacewindow);
        }
        //$("button.cancel",replacewindow).click(PROSJEKT_EDIT_VIEW.onCloseReplaceWindowClicked);
        
        
        // If the user clicks an empty publicationlink, we don't want anything to happen.
        $("a.publikasjonslenke",liElement).click(function(event){
            var linkElement = $(this);
            if( linkElement.hasClass("tompublikasjonslenke")) {
                event.preventDefault();
                return false;
            }
        });
        
        PROSJEKT_EDIT_VIEW.addEditFormHandlers(liElement);
        
    }



    /***********************************************************************************************/
    // Handlers for the buttons that are used to move associations one position upwards in the list.
    /***********************************************************************************************/
    ,onAssociationMoveupButton : function(event)
    {
        var button = $(this);
        var liElement = button.parents("li");
        var language = $("#languageholder").attr("class");
                
        var data = {'associationserial1' : button.parent().attr("id").substr("assoc_".length),
                          'language':language
                         };
        data['operation'] = 'swapassociationorder';
        
        
        var prevElement = liElement.prev("li");
        if(prevElement.length > 0){
            data['associationserial2'] = prevElement.find("div.assoccontrols").attr("id").substr("assoc_".length);
            button.attr("disabled","disabled"); // temporily disable the button, so that the user cannot spam the server by clicking on it repeatedly
            var loadingimg = button.siblings().filter(".loadingimg");
            loadingimg.show();
            liElement.remove().insertBefore(prevElement);
            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(event) { button.removeAttr("disabled");
                                                             loadingimg.hide();
                                                             // We must re-apply the eventhandlers, since they are cleared when the element gets moved.
                                                             PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(liElement);                                                             
                                                            // Make sure the "moveup"-button on the next element is enabled.
                                                            $(".associationmoveupbutton",prevElement).removeAttr("disabled");
                                                            // Disable the "movedown"-button on the old prevElement element, if that element is now the last in the list.
                                                            var nextElement = prevElement.next("li");
                                                            if(nextElement.length == 0){
                                                                $(".associationmovedownbutton",prevElement).attr("disabled","disabled");
                                                            }
                                                            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());

                                                        }
                    , error:     function(event) { button.removeAttr("disabled");
                                                            humanMsg.displayMsg("Failed to move the association!");
                                                            loadingimg.hide();
                                                            // put the element back to its old position
                                                            liElement.remove().insertAfter(prevElement);
                                                             // We must re-apply the eventhandlers, since they are cleared when the element gets moved.
                                                            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(liElement);
                                                            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());

                                                        }
                    });
        }
    }
    
    /***********************************************************************************************/
    // Handlers for the buttons that are used to move associations one position downward in the list.
    /***********************************************************************************************/
    ,onAssociationMovedownButton : function(event)
    {
        var button = $(this);
        var liElement = button.parents("li");
        

        var data = {'associationserial1' : button.parent().attr("id").substr("assoc_".length),
                          'language':PROSJEKT_EDIT_VIEW.language
                         };
        data['operation'] = 'swapassociationorder';
        
        
        var nextElement = liElement.next("li");
        if(nextElement.length > 0){
            data['associationserial2'] = nextElement.find("div.assoccontrols").attr("id").substr("assoc_".length);
            button.attr("disabled","disabled"); // temporily disable the button, so that the user cannot spam the server by clicking on it repeatedly
            var loadingimg = button.siblings().filter(".loadingimg");
            loadingimg.show();
            liElement.remove().insertAfter(nextElement);
            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(event) { button.removeAttr("disabled");
                                                            loadingimg.hide();
                                                            // We must re-apply the eventhandlers, since they are cleared when the element gets moved.
                                                            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(liElement);                                             
                                                            
                                                            // Make sure the "movedown"-button on the old nextElement element is enabled.
                                                            $(".associationmovedownbutton",nextElement).removeAttr("disabled");
                                                            
                                                            // Disable the "moveup"-button on the old nextElement element, if that element is now the first in the list.
                                                            var prevElement = nextElement.prev("li");
                                                            if(prevElement.length == 0){
                                                                $(".associationmoveupbutton",nextElement).attr("disabled","disabled");
                                                            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
                                                            }
                                                        }
                    , error:     function(event) { button.removeAttr("disabled");
                                                            humanMsg.displayMsg("Failed to move the association!");
                                                            loadingimg.hide();
                                                            // put the element back to its old position
                                                            liElement.remove().insertBefore(nextElement);
                                                             // We must re-apply the eventhandlers, since they are cleared when the element gets moved.
                                                            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(liElement);
                                                            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
                                                        }
                    });
        }
    }



    /***********************************************************************************************/
    // Handler for the checkboxes that are used to select the language-scopes of an association.
    /***********************************************************************************************/
    ,onLanguageCheckBox : function(event, onlyAllowOneAssocForEachLanguage)
    {
        var checkbox = $(event.target);
        checkbox.attr("disabled","disabled"); // temporily disable the checkbox, so that the user can spam the server by clicking on it repeatedly
        //humanMsg.displayMsg("onLanguageCheckBox");

        var assoclanguage = checkbox.attr("name");
        var data = {'associationserial' : checkbox.parent().attr("id").substr("assoc_".length),
                          'language':PROSJEKT_EDIT_VIEW.language,
                          'assoclanguage': assoclanguage
                          };
        if( checkbox.attr("checked") ) {
            data['operation'] = 'addassociationscope';
            
            if( onlyAllowOneAssocForEachLanguage ) {            
                var ulParent = $(checkbox.parents("ul").get(0));
                var otherCheckBoxesWithThisLanguage = $("input.languagecheckbox",ulParent).filter("[name='" + assoclanguage + "']").filter(":checked");
                otherCheckBoxesWithThisLanguage.removeAttr("checked");
                otherCheckBoxesWithThisLanguage.click();
                checkbox.attr("checked","checked");
            }
        } else {
            data['operation'] = 'removeassociationscope';
        }
        
        var loadingimg = checkbox.siblings().filter(".loadingimg");
        loadingimg.show();
        

        PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(event) { checkbox.removeAttr("disabled");
                                                             loadingimg.hide();
                                                             }
                    , error:     function(event) { checkbox.removeAttr("disabled");
                                                             humanMsg.displayMsg("Failed to update the association language-setting!");
                                                             loadingimg.hide();
                                                      }
                    });
    }
    
    /***********************************************************************************************/
    // Specialcase handler for the checkboxes that are used to select the language-scopes of an association,
    // when it is only legal to define one association for each language.
    /***********************************************************************************************/
    ,onExclusiveLanguageCheckBox : function(event)
    {
        PROSJEKT_EDIT_VIEW.onLanguageCheckBox(event, true);
    }
    

    /***********************************************************************************************/
    // Handlers for the buttons that are used to delete associations.
    /***********************************************************************************************/
    ,onAssociationDeleteButton : function(event)
    {
        var button = $(this);
        var liElement = button.parents("li");
        if( liElement.hasClass("isUsersOwnPersonTopic") ){
            var msg;
            if( PROSJEKT_EDIT_VIEW.language == 'en' ) {
                msg = "You are about to remove yourself from the project! This might prevent you from being able to edit the project in the future!\n Are you sure you want to do this?";
            } else {
                msg = "Du er i ferd med å fjerne deg selv fra prosjektet! Dette kan føre til at du ikke lenger kan redigere på prosjektet! Er du sikker på at du ønsker å gjøre dette?";
            }
            if(!confirm(msg)) {
                return false;
            }
        }
        
        button.attr("disabled","disabled"); // temporily disable the button, so that the user cannot spam the server by clicking on it repeatedly

        var data = {'associationserial' : button.parent().attr("id").substr("assoc_".length),
                          'language':PROSJEKT_EDIT_VIEW.language
                         };
        data['operation'] = 'deleteassociation';
        
        var loadingimg = liElement.parent().siblings().filter(".loadingimg");
        loadingimg.show();
        liElement.slideUp(1000);
        var ulElement = liElement.parent();
        PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
        
        var topicserial = button.parent().attr("ztm:topicserial");
        var selector = "#topic_" + topicserial.replace(/\./g,"\\.");
        var searchResultLinks = $(selector);
        
        PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(event) { button.removeAttr("disabled");
                                                             searchResultLinks.attr("title",""); // TODO: figure out a way to set the title properly. It is different for publications and documents.
                                                             searchResultLinks.removeClass("selectedTopic");
                                                             
                                                             loadingimg.hide();
                                                             liElement.remove(); // permanently delete the element
                                                             PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
                                                             
                                                             PROSJEKT_EDIT_VIEW.hideOrShowAssocControlsIfNeeded(ulElement);
                                                             
                                                             }
                    , error:     function(event) { button.removeAttr("disabled");
                                                             humanMsg.displayMsg("Failed to delete the association!");
                                                             loadingimg.hide();
                                                             liElement.show(1000); // display the element again, since we failed to delete it.
                                                             PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
                                                      }
                    });
                    
    }
    
    
    
    
    
    // Generic function for adding association search and association add handlers. 
    
    // var utvalgte_publikasjoner = $("div.utvalgte_publikasjoner")
    // var utvalgte_publikasjoner_ulElement = $("ul.utvalgte_publikasjoner",utvalgte_publikasjoner);
    // addSearchAndAddHandlers(utvalgte_publikasjoner,utvalgte_publikasjoner_ulElement,"publication_createassociation",{"this topic":"this publication"});
    //
    // var forskningsfelterDiv = $("div.forskningsfelter");
    // var forskningsfelterUL = $("ul.forskningsfelter",forskningsfelterDiv")
    // addSearchAndAddHandlers(forskningsfelterDiv,forskningsfelterUL, "researchfield_createassociation",{"this topic":"this research field"});
    
    ,addSearchAndAddHandlers : function(parentDiv, parentULElement, createassociationOperation,textMappingsOverride) {
        var textMappings = { "this topic": "this topic"  // typically remapped to something like "this research field"
                            ,"dette emnet":"dette emnet" // typically remapped to something like "dette forskningsfeltet"
                           };
                           
        if( textMappingsOverride != undefined ) {
            var key;
            var value;
            for( key in textMappingsOverride ) {
                value = textMappingsOverride[key];
                textMappings[key] = value;
            }
        }


        parentULElement.children("li").each(function() {
           PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(this);
        });


        /***********************************************************************************************/
        // Handlers for the search controls.
        /***********************************************************************************************/
        var associationcontrols    = $("div.associationcontrols",parentDiv);
        var searchandaddbuttonsbar  = $("div.searchandaddbuttonsbar",associationcontrols);
        var openSearchWindowButton = $("button.search",searchandaddbuttonsbar);
        var openAddNewWindowButton = $("button.addnew",searchandaddbuttonsbar);
        
        var addnewWindow           = $("div.addnewwindow",associationcontrols);
        var addnewWindow_bottom    = $(".addnewwindow_bottom",addnewWindow);
        var closeAddNewWindowButton = $("button.cancel",addnewWindow);
        var addNewTopicButton = $("button.addnew",addnewWindow);
        // TODO: make the list of "addnew"-fields generic somehow, so that we don't have to hardcode the list of fields.
        var addnewTitleTextCtrl        = $("input.title",addnewWindow);
        var addnewURLTextCtrl         = $("input.url",addnewWindow);
        var addnewDescriptionTextCtrl=$("textarea.description",addnewWindow);
        

        var searchWindow           = $("div.searchwindow",associationcontrols);
        var searchWindow_bottom    = $(".searchwindow_bottom",searchWindow);
        var searchTextCtrl         = $("input.searchtext",searchWindow);
        var searchButton           = $("button.search",searchWindow);
        var searchresults          = $("div.searchresults",searchWindow);
        var paginator              = $("div.paginator",searchWindow);
        var nextpagelink           = $(".nextpagelink",paginator);
        var nextpagelink_nopage    = $(".nextpagelink_nopage",paginator);
        var prevpagelink           = $(".prevpagelink",paginator);
        var prevpagelink_nopage    = $(".prevpagelink_nopage",paginator);
        var pagenumber             = $(".pagenumber",paginator);
        var closeSearchWindowButton = $("button.close",searchWindow);
        var currentpage = 0;
        var currentsortkey = "Title";
        var sortreversed = false;

        function updateTopicList(response) {
            var ulElement = parentULElement;//$("ul.utvalgte_publikasjoner",utvalgte_publikasjoner);
            var newline = $(response['newline']);
            ulElement.append(newline);
            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(newline);        
            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
            
            // Make sure the "movedown"-button on previous element is enabled.
            $(".associationmovedownbutton",newline.prev("li")).removeAttr("disabled");

            // The user shouldn't add more than a certain number of publications, so we must hide the associationcontrols if the
            // limit is reached.
            
            PROSJEKT_EDIT_VIEW.hideOrShowAssocControlsIfNeeded(ulElement);
        }

        function getSearchResultTitle(isSelected) {
            if( PROSJEKT_EDIT_VIEW.language == 'en' ) {
                if( isSelected) {
                    return textMappings["this topic"] + " has already been added to the list.";
                } else {
                    return "click here to add " + textMappings["this topic"] + " to the list";
                }
            } else {
                if( isSelected) {
                    return textMappings["dette emnet"] + " har allerede blitt lagt til i listen.";
                } else {
                    return "klikk her for å legge til " + textMappings["dette emnet"] + " i listen";
                }
            }
        }

        // this is called when the user clicks on a searchresult. This will cause a new association to be added.
        function onSearchResultClicked(event) {
            event.preventDefault();
            
            var event_target = $(event.target);
            if(event_target.hasClass("selectedTopic") ){
                // There already exist a reference to this topic, so we don't have to do anything.
                return;
            }
            // Update the link so that the user sees that it has been selected.
            event_target.addClass("selectedTopic");
            event_target.attr("title",getSearchResultTitle(true));
                        
            var tm_serial = $(this).attr("id").substr("topic_".length);
            
            var data = {'language':PROSJEKT_EDIT_VIEW.language,
                        'operation': createassociationOperation,
                        'tm_serial':tm_serial
                        }
            
            var loadingimg = event_target.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 updateTopicList(response);
                                                 //onOnCloseSearchWindowButtonClicked();           
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("Failed to add the association!");
                                                 event_target.removeClass("selectedTopic");
                                                 event_target.attr("title",getSearchResultTitle(false));
                                  }
                    });
            
        }

        // this is called when a search-operation has been succeccfully completed.
        function updateSearchWindow(response) {
            var results = response['results'];
            var language = response['language'];
            var pagecount = response['pagecount'];
            currentpage      = response['page'];
            if( currentpage > 0 ) {
                prevpagelink.show();
                prevpagelink_nopage.hide();
            } else {
                prevpagelink.hide();
                prevpagelink_nopage.show();
            }
            if( currentpage < (pagecount-1) ) {
                nextpagelink.show();
                nextpagelink_nopage.hide();
            } else {
                nextpagelink.hide();
                nextpagelink_nopage.show();
            }

            pagenumber.text(currentpage+1 + ' / ' + pagecount);
            
            searchresults.children().remove();
            
            if( results.length == 0 ) {
                var message = "";
                if(language=="en") {
                    message = "**The search yielded no results**";
                } else {
                    message = "**Søket gav ingen resultater**";
                }
                searchresults.append("<ul><li>" + message +"</li></ul>");
            } else {
                searchresults.append("<ul></ul>");
                var ulElement = $("ul",searchresults);
                var viewLinkText = "";
                if(language == "en" ) {
                    viewLinkText = "[view]";
                } else {
                    viewLinkText = "[vis]";
                }
                for (var i=0; i<results.length; i++) {
                    result = results[i];
                    aclass = "select"
                    var isSelected = result['isSelected'];
                    var atitle = getSearchResultTitle(isSelected);
                    if(isSelected){
                        aclass += " selectedTopic";
                    }
                    ulElement.append('<li><a id="topic_' + result['tm_serial'] + '" href="' + result['url'] + '" class="' + aclass +'" title="' + atitle + '">' +result['name'] + '</a>&nbsp;<a class="view" target="_blank" href="' + result['url'] + '">' + viewLinkText + '</a><span class="loadingimg" style="display:none">...</span></li>');
                }
                $('a.select',ulElement).click(onSearchResultClicked);
            }
        }
        

        function onOpenSearchWindowButtonClicked(event){
            // temporily disable the buttons, so that the user cannot spam the server by clicking on them repeatedly.
            openSearchWindowButton.attr("disabled","disabled");
            openAddNewWindowButton.attr("disabled","disabled");
            searchTextCtrl.val('');
            
            var button = $(event.target);
            var operation = button.attr("name"); // the "name"-attr contains 'externalpublicationsearch' or 'ssbpublicationsearch'
            searchButton.attr("name",operation); // the "search"-button must be updated, so that it remembers the type of search it should perform.

            var data = {'language':PROSJEKT_EDIT_VIEW.language,
                        'operation': operation,
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { 
                                                searchandaddbuttonsbar.slideUp(500);
                                                updateSearchWindow(response);
                                                
                                                searchWindow.slideDown(500)
                                                if( $.browser.msie ) {
                                                    // IE doesn't display the text-controls if we just try to do a fancy animation. It seems to 
                                                    // work to toggle the visibility on and off, though.
                                                    window.setTimeout(function() {
                                                                                searchWindow.hide();
                                                                                searchWindow.show();
                                                                                },
                                                                                600);
                                                } 
                                                 
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                }
                    });
        }
        openSearchWindowButton.click(onOpenSearchWindowButtonClicked);
        
        function onOnCloseSearchWindowButtonClicked(event) {
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            searchWindow.slideUp(1000);        
        }
        closeSearchWindowButton.click(onOnCloseSearchWindowButtonClicked);    
        
        // This is called when the Search-button in the search-window is clicked. It is
        // also called by the eventhandlers of the other elements that can start a search
        // (for instance the "prev" and "next" links)
        function onSearchButtonClicked(event) {
            var button = $(event.target);
            var operation = button.attr("name"); // the "name"-attr contains 'externalpublicationsearch' or 'ssbpublicationsearch'
				if (operation == '') { // une@ssb.no ugly hack to get the operation
					 button = $(event.target.parentNode.parentNode.getElementsByTagName('button')[0]);
					 operation = button.attr("name");
				}            
            var data = {'language': PROSJEKT_EDIT_VIEW.language,
                        'operation': operation,
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            // Disable all the search-controls, so that the user cannot spam the server by clicking
            // stuff repeatedly.
            searchButton.attr("disabled","disabled");
            searchTextCtrl.attr("disabled","disabled");
            nextpagelink.hide();
            nextpagelink_nopage.show();
            prevpagelink.hide();
            prevpagelink_nopage.show();

            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { 
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                 updateSearchWindow(response);
                                                 //$.scrollTo(searchWindow_bottom,1000);
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                }
                    });
        }
        searchButton.click(onSearchButtonClicked);
        
        
        // This is called when the user wants to go to the next page of search-results
        function onNextPageLinkClicked(event) {
            event.preventDefault(); 
            currentpage += 1;
            onSearchButtonClicked(event);        
        }
        nextpagelink.click(onNextPageLinkClicked);
        
        // This is called when the user wants to go to the previous page of search-results
        function onPrevPageLinkClicked(event) {
            event.preventDefault();
            currentpage -= 1;
            onSearchButtonClicked(event);
        }    
        prevpagelink.click(onPrevPageLinkClicked);

        function onSearchTextCtrlKeyDown(event) {
            if(event.which == 13 ) {
                onSearchButtonClicked(event);        
                event.preventDefault();
                return false;
            }
        }
        searchTextCtrl.keydown(onSearchTextCtrlKeyDown);
        
        
        
        
        
        /***********************************************************************************************/
        // Handlers for the "add new publication" controls.
        /***********************************************************************************************/
        function onOpenAddNewWindowButton(event) {
            searchandaddbuttonsbar.slideUp(500);
            //$.scrollTo("+=200px",500);
            addnewWindow.slideDown(500, function() 
                {
                    //$.scrollTo(addnewWindow_bottom,500);
                });
            
            if( $.browser.msie ) {
                // IE doesn't display the text-controls if we just try to do a fancy animation. It seems to 
                // work to toggle the visibility on and off, though.
                window.setTimeout(function() {
                                            addnewWindow.hide();
                                            addnewWindow.show();
                                            },
                                            600);
            } 
                
        }
        openAddNewWindowButton.click(onOpenAddNewWindowButton);
        
        function onCloseAddNewWindowButton(event) {
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            addNewTopicButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            addnewWindow.slideUp(1000);
        }
        closeAddNewWindowButton.click(onCloseAddNewWindowButton);    
        
        function onaddNewTopicButton(event) {        
            // Disable the add-button, so that the user cannot spam the server by clicking
            // it repeatedly. TODO: make this function generic, so that we don't have to hardcode
            // the list of form-values.
            addNewTopicButton.attr("disabled","disabled");
            var data = {'language':PROSJEKT_EDIT_VIEW.language,
                        'operation': 'createpublicationlink',
                        'title':addnewTitleTextCtrl.val(),
                        'url':addnewURLTextCtrl.val(),
                        'description':addnewDescriptionTextCtrl.attr("value")
                        }
            
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 updateTopicList(response);
                                                 onCloseAddNewWindowButton();                                             
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                addNewTopicButton.removeAttr("disabled");
                                                humanMsg.displayMsg("Failed to create a new topic!"); 
                                                }
                    });


        }
        addNewTopicButton.click(onaddNewTopicButton);        

    } // addSearchAndAddHandlers() {

};
$(document).ready(function() {
    PROSJEKT_EDIT_VIEW.initialize();

    // The pagetemplate stores the current language in a html-element, so that we can get at it.
    var language = $("#languageholder").attr("class");
    //humanMsg.displayMsg("language"+language)
      
    // Set up the language-selection link (it is in the upper right corner of the page), so that it points to the correct
    // url and has the correct url-parameters.
    var newlanguage = "";
    if( language == "en" ) {
        newlanguage = "no";
    } else {
        newlanguage = "en";
    }
    // Check if the page is in editmode
    var editmodeParam ="";
    var editmode =  $("#editmode") ;
    // humanMsg.displayMsg("editmode:"+editmode)
    if(editmode.length) {
        editmodeParam = "&edit=1";
    } else {
        editmodeParam = "";
    }
    
    
    
                
    if(editmode.length) {
        // Setup the datetime widgets.
        function applyCalendar(element) {
            // Create button
            var button = document.createElement('input');
            button.type = 'image';
            button.style.width = '16px';
            button.style.height = '16px';
            button.style.margin = '2px 0px 0px 4px';
            button.id = element.id + '_button';
            button.src = PROSJEKT_EDIT_VIEW.portalURL + '/img/cal.gif';
            button.value = 'Calendar';
            element.parentNode.appendChild(button);

            var curdate = new Date();
            curdate.setHours(10,00,00);
            
            function onSelect(calendar, date) {
                element.value = date;
                // trigger the onchange-eventhandler, so that the "Save text changes" button is activated
                $(element).change();
                if (calendar.dateClicked) {
                    calendar.callCloseHandler(); // this calls "onClose" (see above)
                }
            };
            
            var calendar = Calendar.setup(
                {
                inputField  : element.id,         // ID of the input field
                ifFormat    : "%d.%m.%Y %H:%M",    // the date format
                button      : element.id + '_button',       // ID of the button
                showsTime   : true,
                showOthers  : true,
                date        : curdate,
                onSelect    : onSelect
                }
            );
        }
        $("input.datetime").each(function(index,inputelement) {
            applyCalendar(inputelement);
            }
            );
    }
    
    
    if(location.hostname == "publiser.ssb.no" || location.hostname == "zope.ssb.no") {
        $("a.verktoylinjetekst[@href=http://www.ssb.no/english][@onclick]:contains('English')").removeAttr("onclick").attr("href","?language=" + newlanguage + editmodeParam); // works for the link to the english version
        $("a.verktoylinjetekst[@href=http://www.ssb.no/][@onclick]:contains('Norwegian')").removeAttr("onclick").attr("href","?language=" + newlanguage + editmodeParam); // works for the link to the norwegian version
    }

    // Add the eventhandler for the show/hide finished projects link.
    $("a.visavsluttedeprosjekter").click(PROSJEKT_EDIT_VIEW.onVisAvsluttedeProsjekterClicked);
    $("a.skjulavsluttedeprosjekter").click(PROSJEKT_EDIT_VIEW.onSkjulAvsluttedeProsjekterClicked);

    // Add the eventhandler for the show/hide additinalimages link.
    $("a.showadditionalimages").click(PROSJEKT_EDIT_VIEW.onShowAdditionalImagesClicked);
    $("a.hideadditionalimages").click(PROSJEKT_EDIT_VIEW.onHideAdditionalImagesClicked);
    

    /* Prevent the user from accidentally browsing away from the page without saving his changes first..
    The 'hasUnsavedChanges' variable will be set to true whenever the user has made a change to a textfield. It will be set to 
    false again when the user hits the "Save" button.
    */
    var hasUnsavedChanges = false; 
    function confirmBrowseAway()
    {
        if (hasUnsavedChanges) {
            var msg = "";
            if( language == "en" ) {
                msg = "If you leave this page now, your work will NOT be saved!";
            } else {
                msg = "Dersom du forlater siden nå vil endringene du har gjort IKKE bli lagret!";
            }
           return msg;
        }
        return undefined;
    } 
    window.onbeforeunload = confirmBrowseAway;
   
    
    // Enable the elements that needs javascript to work (edit-links, submit-buttons, etc)
    $(".enablewithjavascript").removeClass("enablewithjavascript");
   
   
   
    /***********************************************************************************************/
    // Handlers for the textareas: These fields are stored as occurrences on the projecttopic.
    /***********************************************************************************************/
    // Get the "Save"-button(s). These should be initially disabled, and should be enabled when the user makes a change to a textarea.
    var saveButtons = $("input.textareasubmit");
    var form = $(saveButtons).parents('form');
    saveButtons.attr("disabled","disabled");
    saveButtons.hide();

    saveButtons.click(onSaveButtonClicked);
   
    // add onchange events on the textareas, so that the "Save"-button is enabled when a the user modifies the text,
    // and set the "hasUnsavedChanges" variable, so that the user will get a warning if he tries to leave the page.
    var textFields = $(".occurrencetextfield");
    function onTextAreaChanged(event) {
        if( hasUnsavedChanges == false) {
            saveButtons.removeAttr("disabled");
            saveButtons.show(1000);
            hasUnsavedChanges = true;
        }
    }
    onTinyMCEEditorChanged.onTextAreaChanged = onTextAreaChanged;
    function onTextAreaKeyDown(e) {
        if (e.which == 32 || (65 <= e.which && e.which <= 65 + 25)
                                 || (97 <= e.which && e.which <= 97 + 25)
                                 || e.which == 8 // backspace
                                 || e.which == 46 // delete
                                 ) {
            // this looks like the user has edited the text. Note that this check doesn't have to be perfect, since the
            // "change" eventhandler will always trigger when a modified textfield looses the input focus. This check
            // is only used to give the user immediate feedback.
            onTextAreaChanged(e);
        } /*else {
            humanMsg.displayMsg("unknown keycode:" + e.which);
        }*/
        
        // prevent hits on the "Enter"-key to propagate. If we don't IE6 sometimes opens one of the
        // calendar-widgets.
        if( ( e.witch == 13 ) && (event.target.nodeName == "INPUT" ) ) {
            event.preventDefault();
            return false;
        }
        
    }
    textFields.change(onTextAreaChanged);
    textFields.keydown(onTextAreaKeyDown);
    
    function onSaveButtonClicked(event)
    {
        if( tinyMCE.activeEditor.isDirty() ) {
            // Store the contents of the tiny_mce editor in the textField.
            var content = tinyMCE.activeEditor.getContent();
            textFields.filter(".simplewysiwyg").attr("value",content);
            
            // Reset the "startContent" variable of the tiny_mce-editor, so that tinyMCE.activeEditor.isDirty()  
            // will return false until a new change is made to the text.
            var newContent = tinymce.trim(tinyMCE.activeEditor.getBody().innerHTML);
            tinyMCE.activeEditor.startContent = newContent;
        }
        saveButtons.attr("disabled","disabled");        

        var data = {'operation' : 'savetextfields','language':language};
        var values = {};
        textFields.each(function(index){
             values[$(this).attr("id")] =  $(this).attr("value");
        });
        data['values'] = values;

        PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
//                    , timeout: 5000
                    , success: saveSucceded
                    , error: saveFailed
                    });
                    
        event.preventDefault();
        return false;
    }
    function saveSucceded(event) {
        /*if( language=='en') {
            msg = "The save-operation suceeded.";
        } else {
            msg = "Lagret ok.";
        }
        humanMsg.displayMsg(msg);
        */
        hasUnsavedChanges = false;
        saveButtons.hide(1000);
        
    }
    function saveFailed(event) {
        if( language=='en') {
            msg = "The save-operation failed!";
        } else {
            msg = "Lagringen mislyktes!";
        }
        humanMsg.displayMsg(msg);
        saveButtons.removeAttr("disabled");
    }
   
   
   



    /***********************************************************************************************/
    // Handlers for the "selected publications" list. These are stored as separate topics (which can be of 
    // several different topictypes) with associations to the person-topic. The user can either search for an
    // existing topic, or create a new topic by entering a title, description and url.
    // The user can also specify which languages each association should be scoped with.
    /***********************************************************************************************/






    $("li.utvalgte_publikasjoner").each(function(index) {
       PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(this);
    });
    $("li.selecteddocument").each(function(index) {
       PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(this);
    });
    
    if( editmode.length ) {
        //We use a negative margin-top, to push the "norsk engelsk" header-line a bit up.
        //$("div.selecteddocuments").css("margin-top","-1em"); 
        //$("div.utvalgte_publikasjoner").css("margin-top","-1em"); 
            
    }
    
    
    var forskningsfelterDiv = $("div.forskningsfelter");
    var forskningsfelterUL = $("ul.forskningsfelter",forskningsfelterDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(forskningsfelterDiv,forskningsfelterUL, 
                                             "forskningsfelter_createassociation",
                                             {  "this topic"  :"this research field"
                                               ,"dette emnet" :"dette forskningsfeltet"
                                             }
                                             );
    
    var ledereDiv = $("div.ledere");
    var ledereUL = $("ul.ledere",ledereDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(ledereDiv,ledereUL, 
                                             "ledere_createassociation",
                                             {  "this topic"  :"this project manager"
                                               ,"dette emnet" :"denne lederen"
                                             }
                                             );
    
    var kontaktpersonerDiv = $("div.kontaktpersoner");
    var kontaktpersonerUL = $("ul.kontaktpersoner",kontaktpersonerDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(kontaktpersonerDiv,kontaktpersonerUL, 
                                             "kontaktpersoner_createassociation",
                                             {  "this topic"  :"this contact"
                                               ,"dette emnet" :"denne kontaktpersonen"
                                             }
                                             );
    
    
    var deltagereDiv = $("div.deltagere");
    var deltagereUL = $("ul.deltagere",deltagereDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(deltagereDiv,deltagereUL, 
                                             "deltagere_createassociation",
                                             {  "this topic"  :"this project assistant"
                                               ,"dette emnet" :"denne deltageren"
                                             }
                                             );
    
    var lenkerDiv = $("div.lenker");
    var lenkerUL = $("ul.lenker",lenkerDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(lenkerDiv,lenkerUL, 
                                             "lenker_createassociation",
                                             {  "this topic"  :"this project assistant"
                                               ,"dette emnet" :"denne lenkern"
                                             }
                                             );
    
    
    var begivenheterDiv = $("div.begivenheter");
    var begivenheterUL = $("ul.begivenheter",begivenheterDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(begivenheterDiv,begivenheterUL, 
                                             "begivenheter_createassociation",
                                             {  "this topic"  :"this project assistant"
                                               ,"dette emnet" :"denne begivenhetern"
                                             }
                                             );
    
    var selectedarticlesDiv = $("div.selectedarticles");
    var selectedarticlesUL = $("ul.selectedarticles",selectedarticlesDiv)
    PROSJEKT_EDIT_VIEW.addSearchAndAddHandlers(selectedarticlesDiv,selectedarticlesUL, 
                                             "selectedarticles_createassociation",
                                             {  "this topic"  :"this article"
                                               ,"dette emnet" :"denne artikkelen"
                                             }
                                             );
    


    PROSJEKT_EDIT_VIEW.hideOrShowAssocControlsIfNeeded($("ul.utvalgte_publikasjoner"));


    // TODO: make generic functions for the search-functionality, so that we don't have lots of copy-paste code
    function publicationSearchNameSpace(){
        /***********************************************************************************************/
        // Handlers for the "search for publication" controls.
        /***********************************************************************************************/
        var utvalgte_publikasjoner = $("div.utvalgte_publikasjoner");
        var associationcontrols    = $("div.associationcontrols",utvalgte_publikasjoner);
        var searchandaddbuttonsbar  = $("div.searchandaddbuttonsbar",associationcontrols);
        var openSearchWindowButton = $("button.search",searchandaddbuttonsbar);
        var openAddNewWindowButton = $("button.addnew",searchandaddbuttonsbar);
        
        var addnewWindow           = $("div.addnewwindow",associationcontrols);
        var addnewWindow_bottom    = $(".addnewwindow_bottom",addnewWindow);
        var closeAddNewWindowButton = $("button.cancel",addnewWindow);
        var addNewPublicationButton = $("button.addnew",addnewWindow);
        var addnewTitleTextCtrl        = $("input.title",addnewWindow);
        var addnewURLTextCtrl         = $("input.url",addnewWindow);
        var addnewPublikasjonsnavnTextCtrl = $("input.publikasjonsnavn",addnewWindow);
        var addnewDescriptionTextCtrl=$("textarea.description",addnewWindow);
        

        var searchWindow           = $("div.searchwindow",associationcontrols);
        var searchWindow_bottom    = $(".searchwindow_bottom",searchWindow);
        var searchTextCtrl         = $("input.searchtext",searchWindow);
        var searchButton           = $("button.search",searchWindow);
        var searchresults          = $("div.searchresults",searchWindow);
        var paginator              = $("div.paginator",searchWindow);
        var nextpagelink           = $(".nextpagelink",paginator);
        var nextpagelink_nopage    = $(".nextpagelink_nopage",paginator);
        var prevpagelink           = $(".prevpagelink",paginator);
        var prevpagelink_nopage    = $(".prevpagelink_nopage",paginator);
        var pagenumber             = $(".pagenumber",paginator);
        var closeSearchWindowButton = $("button.close",searchWindow);
        var currentpage = 0;
        var currentsortkey = "Title";
        var sortreversed = false;

        function updatePublicationList(response) {
            var ulElement = $("ul.utvalgte_publikasjoner",utvalgte_publikasjoner);
            var newline = $(response['newline']);
            ulElement.append(newline);
            PROSJEKT_EDIT_VIEW.addPublicationOrDocumentLineHandlers(newline);        
            PROSJEKT_EDIT_VIEW.setEvenAndOddClasses(ulElement);
            
            // Make sure the "movedown"-button on previous element is enabled.
            $(".associationmovedownbutton",newline.prev("li")).removeAttr("disabled");

            // The user shouldn't add more than a certain number of publications, so we must hide the associationcontrols if the
            // limit is reached.
            
            PROSJEKT_EDIT_VIEW.hideOrShowAssocControlsIfNeeded(ulElement);
        }

        function getSearchResultTitle(isSelected) {
            if( language == 'en' ) {
                if( isSelected) {
                    return "This publication has already been added to the list.";
                } else {
                    return "Click here to add this publication to the list";
                }
            } else {
                if( isSelected) {
                    return "Denne publikasjonen har allerede blitt lagt til i listen.";
                } else {
                    return "Klikk her for å legge til denne publikasjonen i listen";
                }
            }
        }

        // this is called when the user clicks on a searchresult. This will cause a new association to be added.
        function onSearchResultClicked(event) {
            event.preventDefault();
            
            var event_target = $(event.target);
            if(event_target.hasClass("selectedTopic") ){
                // There already exist a reference to this topic, so we don't have to do anything.
                return;
            }
            // Update the link so that the user sees that it has been selected.
            event_target.addClass("selectedTopic");
            event_target.attr("title",getSearchResultTitle(true));
                        
            var tm_serial = $(this).attr("id").substr("topic_".length);
            
            var data = {'language':language,
                        'operation': 'createassociation',
                        'tm_serial':tm_serial
                        }
            
            var loadingimg = event_target.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 updatePublicationList(response);
                                                 //onOnCloseSearchWindowButtonClicked();           
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("Failed to add the association!");
                                                 event_target.removeClass("selectedTopic");
                                                 event_target.attr("title",getSearchResultTitle(false));
                                  }
                    });
            
        }

        // this is called when a search-operation has been succeccfully completed.
        function updateSearchWindow(response) {
            var results = response['results'];
            var language = response['language'];
            var pagecount = response['pagecount'];
            currentpage      = response['page'];
            if( currentpage > 0 ) {
                prevpagelink.show();
                prevpagelink_nopage.hide();
            } else {
                prevpagelink.hide();
                prevpagelink_nopage.show();
            }
            if( currentpage < (pagecount-1) ) {
                nextpagelink.show();
                nextpagelink_nopage.hide();
            } else {
                nextpagelink.hide();
                nextpagelink_nopage.show();
            }

            pagenumber.text(currentpage+1 + ' / ' + pagecount);
            
            searchresults.children().remove();
            
            if( results.length == 0 ) {
                var message = "";
                if(language=="en") {
                    message = "**The search yielded no results**";
                } else {
                    message = "**Søket gav ingen resultater**";
                }
                searchresults.append("<ul><li>" + message +"</li></ul>");
            } else {
                searchresults.append("<ul></ul>");
                var ulElement = $("ul",searchresults);
                var viewLinkText = "";
                if(language == "en" ) {
                    viewLinkText = "[view]";
                } else {
                    viewLinkText = "[vis]";
                }
                for (var i=0; i<results.length; i++) {
                    result = results[i];
                    aclass = "select"
                    var isSelected = result['isSelected'];
                    var atitle = getSearchResultTitle(isSelected);
                    if(isSelected){
                        aclass += " selectedTopic";
                    }
                    ulElement.append('<li><a id="topic_' + result['tm_serial'] + '" href="' + result['url'] + '" class="' + aclass +'" title="' + atitle + '">' +result['name'] + '</a>&nbsp;<a class="view" target="_blank" href="' + result['url'] + '">' + viewLinkText + '</a><span class="loadingimg" style="display:none">...</span></li>');
                }
                $('a.select',ulElement).click(onSearchResultClicked);
            }
        }
        

        function onOpenSearchWindowButtonClicked(event){
            // temporily disable the buttons, so that the user cannot spam the server by clicking on them repeatedly.
            openSearchWindowButton.attr("disabled","disabled");
            openAddNewWindowButton.attr("disabled","disabled");
            searchTextCtrl.val('');
            var button = $(event.target);
            var operation = button.attr("name"); // the "name"-attr contains 'externalpublicationsearch' or 'ssbpublicationsearch'
            searchButton.attr("name",operation); // the "search"-button must be updated, so that it remembers the type of search it should perform.
            var data = {'language':language,
                        'operation': operation,
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { 
                                                searchandaddbuttonsbar.slideUp(500);
                                                updateSearchWindow(response);
                                                
                                                //$.scrollTo("+=250px",500);
                                                searchWindow.slideDown(500, function() {
                                                  //$.scrollTo(searchWindow_bottom,500);
                                                  } );
                                                
                                                if( $.browser.msie ) {
                                                    // IE doesn't display the text-controls if we just try to do a fancy animation. It seems to 
                                                    // work to toggle the visibility on and off, though.
                                                    window.setTimeout(function() {
                                                                                searchWindow.hide();
                                                                                searchWindow.show();
                                                                                //$.scrollTo(searchWindow_bottom);
                                                                                },
                                                                                600);
                                                } 
                                                 
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                }
                    });
        }
        openSearchWindowButton.click(onOpenSearchWindowButtonClicked);
        
        function onOnCloseSearchWindowButtonClicked(event) {
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            searchWindow.slideUp(1000);        
        }
        closeSearchWindowButton.click(onOnCloseSearchWindowButtonClicked);    
        
        // This is called when the Search-button in the search-window is clicked. It is
        // also called by the eventhandlers of the other elements that can start a search
        // (for instance the "prev" and "next" links)
        function onSearchButtonClicked(event) {
            var button = $(event.target);
            var operation = button.attr("name"); // the "name"-attr contains 'externalpublicationsearch' or 'ssbpublicationsearch'
            if (operation == '') { // une@ssb.no ugly hack to get the operation
                button = $(event.target.parentNode.parentNode.getElementsByTagName('button')[0]);
                operation = button.attr("name");
            }
            var data = {'language':language,
                        'operation': operation,
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            // Disable all the search-controls, so that the user cannot spam the server by clicking
            // stuff repeatedly.
            searchButton.attr("disabled","disabled");
            searchTextCtrl.attr("disabled","disabled");
            nextpagelink.hide();
            nextpagelink_nopage.show();
            prevpagelink.hide();
            prevpagelink_nopage.show();

            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { 
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                 updateSearchWindow(response);
                                                 //$.scrollTo(searchWindow_bottom,1000);
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                }
                    });
        }
        searchButton.click(onSearchButtonClicked);
        
        
        // This is called when the user wants to go to the next page of search-results
        function onNextPageLinkClicked(event) {
            event.preventDefault(); 
            currentpage += 1;
            onSearchButtonClicked(event);        
        }
        nextpagelink.click(onNextPageLinkClicked);
        
        // This is called when the user wants to go to the previous page of search-results
        function onPrevPageLinkClicked(event) {
            event.preventDefault();
            currentpage -= 1;
            onSearchButtonClicked(event);
        }    
        prevpagelink.click(onPrevPageLinkClicked);

        function onSearchTextCtrlKeyDown(event) {
            if(event.which == 13 ) {
                onSearchButtonClicked(event);        
                event.preventDefault();
                return false;
            }
        }
        searchTextCtrl.keydown(onSearchTextCtrlKeyDown);
        
        
        
        
        
        /***********************************************************************************************/
        // Handlers for the "add new publication" controls.
        /***********************************************************************************************/
        function onOpenAddNewWindowButton(event) {
            addnewTitleTextCtrl.val('');
            addnewURLTextCtrl.val('');
            addnewPublikasjonsnavnTextCtrl.val('');
            addnewDescriptionTextCtrl.val('');
        
            searchandaddbuttonsbar.slideUp(500);
            //$.scrollTo("+=200px",500);
            addnewWindow.slideDown(500, function() 
                {
                    //$.scrollTo(addnewWindow_bottom,500);
                });
            
            if( $.browser.msie ) {
                // IE doesn't display the text-controls if we just try to do a fancy animation. It seems to 
                // work to toggle the visibility on and off, though.
                window.setTimeout(function() {
                                            addnewWindow.hide();
                                            addnewWindow.show();
                                            },
                                            600);
            } 
                
        }
        openAddNewWindowButton.click(onOpenAddNewWindowButton);
        
        function onCloseAddNewWindowButton(event) {
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            addNewPublicationButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            addnewWindow.slideUp(1000);
        }
        closeAddNewWindowButton.click(onCloseAddNewWindowButton);    
        
        function onAddNewPublicationButton(event) {        
            // Disable the add-button, so that the user cannot spam the server by clicking
            // it repeatedly.
            addNewPublicationButton.attr("disabled","disabled");
            var data = {'language':language,
                        'operation': 'createpublicationlink',
                        'title':addnewTitleTextCtrl.val(),
                        'url':addnewURLTextCtrl.val(),
                        'publikasjonsnavn':addnewPublikasjonsnavnTextCtrl.val(),
                        'description':addnewDescriptionTextCtrl.attr("value")
                        }
            
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 updatePublicationList(response);
                                                 onCloseAddNewWindowButton();                                             
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                addNewPublicationButton.removeAttr("disabled");
                                                humanMsg.displayMsg("Failed to create a new publication-link!"); 
                                                }
                    });


        }
        addNewPublicationButton.click(onAddNewPublicationButton);        
    } // publicationSearchNameSpace
    publicationSearchNameSpace();
    



    // TODO: make generic functions for the search-functionality, so that we don't have lots of copy-paste code
    function selecteddocumentSearchNameSpace(){
        /***********************************************************************************************/
        // Handlers for the "search for selecteddocument" controls.
        /***********************************************************************************************/
        var selecteddocuments = $("div.selecteddocuments");
        var associationcontrols    = $("div.associationcontrols",selecteddocuments);
        var searchandaddbuttonsbar  = $("div.searchandaddbuttonsbar",associationcontrols);
        var openSearchWindowButton = $("button.search",searchandaddbuttonsbar);
        var openAddNewWindowButton = $("button.addnew",searchandaddbuttonsbar);
        
        var addnewWindow           = $("div.addnewwindow",associationcontrols);
        var addnewWindow_bottom    = $(".addnewwindow_bottom",addnewWindow);
        var closeAddNewWindowButton = $("button.cancel",addnewWindow);
        var addnewTitleTextCtrl        = $("input.title",addnewWindow);
        var addnewURLTextCtrl         = $("input.url",addnewWindow);
        var addnewDescriptionTextCtrl=$("textarea.description",addnewWindow);
        

        var searchWindow           = $("div.searchwindow",associationcontrols);
        var searchWindow_bottom    = $(".searchwindow_bottom",searchWindow);
        var searchTextCtrl         = $("input.searchtext",searchWindow);
        var searchButton           = $("button.search",searchWindow);
        var searchresults          = $("div.searchresults",searchWindow);
        var paginator              = $("div.paginator",searchWindow);
        var nextpagelink           = $(".nextpagelink",paginator);
        var nextpagelink_nopage    = $(".nextpagelink_nopage",paginator);
        var prevpagelink           = $(".prevpagelink",paginator);
        var prevpagelink_nopage    = $(".prevpagelink_nopage",paginator);
        var pagenumber             = $(".pagenumber",paginator);
        var closeSearchWindowButton = $("button.close",searchWindow);
        var currentpage = 0;
        var currentsortkey = "Title";
        var sortreversed = false;


        // this is called when the user clicks on a searchresult. This will cause a new association to be added.
        function onSearchResultClicked(event) {
            event.preventDefault();
            
            var event_target = $(event.target);
            if(event_target.hasClass("selectedTopic") ){
                // There already exist a reference to this topic, so we don't have to do anything.
                return;
            }
            // Update the link so that the user sees that it has been selected.
            event_target.addClass("selectedTopic");
            event_target.attr("title",getSearchResultTitle(true));
            
            var tm_serial = $(this).attr("id").substr("topic_".length);
            
            var data = {'language':language,
                        'operation': 'document_createassociation',
                        'tm_serial':tm_serial
                        }
            
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 PROSJEKT_EDIT_VIEW.updateSelectedDocumentList(response);
                                                 //onOnCloseSearchWindowButtonClicked();                                             
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("Failed to add the association!"); 
                                                 event_target.removeClass("selectedTopic");
                                                 event_target.attr("title",getSearchResultTitle(false));
                                                }
                    });
            
        }

        // this is called when a search-operation has been succeccfully completed.
        function updateSearchWindow(response) {
            var results = response['results'];
            var language = response['language'];
            var pagecount = response['pagecount'];
            currentpage      = response['page'];
            if( currentpage > 0 ) {
                prevpagelink.show();
                prevpagelink_nopage.hide();
            } else {
                prevpagelink.hide();
                prevpagelink_nopage.show();
            }
            if( currentpage < (pagecount-1) ) {
                nextpagelink.show();
                nextpagelink_nopage.hide();
            } else {
                nextpagelink.hide();
                nextpagelink_nopage.show();
            }

            pagenumber.text(currentpage+1 + ' / ' + pagecount);
            
            searchresults.children().remove();
            
            if( results.length == 0 ) {
                var message = "";
                if(language=="en") {
                    message = "**The search yielded no results**";
                } else {
                    message = "**Søket gav ingen resultater**";
                }
                searchresults.append("<ul><li>" + message +"</li></ul>");
            } else {
                searchresults.append("<ul></ul>");
                var ulElement = $("ul",searchresults);
                var viewLinkText = "";
                if(language == "en" ) {
                    viewLinkText = "[view]";
                } else {
                    viewLinkText = "[vis]";
                }
                for (var i=0; i<results.length; i++) {
                    result = results[i];
                    aclass = "select"
                    var isSelected = result['isSelected'];
                    var atitle = getSearchResultTitle(isSelected);
                    if(isSelected){
                        aclass += " selectedTopic";
                    }
                    ulElement.append('<li><a id="topic_' + result['tm_serial'] + '" href="' + result['url'] + '" class="' + aclass +'" title="' + atitle + '">' +result['name'] + '</a>&nbsp;<a class="view" target="_blank" href="' + result['url'] + '">' + viewLinkText + '</a><span class="loadingimg" style="display:none">...</span></li>');
                }
                $('a.select',ulElement).click(onSearchResultClicked);
            }
        }
        
        function getSearchResultTitle(isSelected) {
            if( language == 'en' ) {
                if( isSelected) {
                    return "This file has already been added to the list.";
                } else {
                    return "Click here to add this file to the list";
                }
            } else {
                if( isSelected) {
                    return "Denne filen har allerede blitt lagt til i listen.";
                } else {
                    return "Klikk her for å legge til denne filen i listen";
                }
            }
        }


        function onOpenSearchWindowButtonClicked(event){
            // temporily disable the buttons, so that the user cannot spam the server by clicking on them repeatedly.
            openSearchWindowButton.attr("disabled","disabled");
            openAddNewWindowButton.attr("disabled","disabled");
            searchTextCtrl.val('');
            var data = {'language':language,
                        'operation': 'document_search',
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { searchandaddbuttonsbar.slideUp(500);
                                                 updateSearchWindow(response);
                                                 //$.scrollTo("+=250px",500);
                                                 searchWindow.slideDown(500);
                                                 //, function() {$.scrollTo(searchWindow_bottom,500);});
                                                 
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                }
                    });
        }
        openSearchWindowButton.click(onOpenSearchWindowButtonClicked);
        
        function onOnCloseSearchWindowButtonClicked(event) {
            openSearchWindowButton.removeAttr("disabled");
            openAddNewWindowButton.removeAttr("disabled");
            searchandaddbuttonsbar.slideDown(1000);
            searchWindow.slideUp(1000);        
        }
        closeSearchWindowButton.click(onOnCloseSearchWindowButtonClicked);    
        
        // This is called when the Search-button in the search-window is clicked. It is
        // also called by the eventhandlers of the other elements that can start a search
        // (for instance the "prev" and "next" links)
        function onSearchButtonClicked(event) {
            var data = {'language':language,
                        'operation': 'document_search',
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            // Disable all the search-controls, so that the user cannot spam the server by clicking
            // stuff repeatedly.
            searchButton.attr("disabled","disabled");
            searchTextCtrl.attr("disabled","disabled");
            nextpagelink.hide();
            nextpagelink_nopage.show();
            prevpagelink.hide();
            prevpagelink_nopage.show();

            PROSJEKT_EDIT_VIEW.postJSON({ url : PROSJEKT_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { 
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                 updateSearchWindow(response);
                                                 //$.scrollTo(searchWindow_bottom,1000);
                                                 loadingimg.hide();
                                                }
                    , error:   function(event) { loadingimg.hide();
                                                 humanMsg.displayMsg("The search-operation failed!"); 
                                                 searchButton.removeAttr("disabled");
                                                 searchTextCtrl.removeAttr("disabled");
                                                }
                    });
        }
        searchButton.click(onSearchButtonClicked);
        
        
        // This is called when the user wants to go to the next page of search-results
        function onNextPageLinkClicked(event) {
            event.preventDefault(); 
            currentpage += 1;
            onSearchButtonClicked(event);        
        }
        nextpagelink.click(onNextPageLinkClicked);
        
        // This is called when the user wants to go to the previous page of search-results
        function onPrevPageLinkClicked(event) {
            event.preventDefault();
            currentpage -= 1;
            onSearchButtonClicked(event);
        }    
        prevpagelink.click(onPrevPageLinkClicked);

        function onSearchTextCtrlKeyDown(event) {
            if(event.which == 13 ) {
                onSearchButtonClicked(event);   
                event.preventDefault();
                return false;
            }
        }
        searchTextCtrl.keydown(onSearchTextCtrlKeyDown);
        
        
        
        
        
        /***********************************************************************************************/
        // Handlers for the "add new document" controls.
        /***********************************************************************************************/
        PROSJEKT_EDIT_VIEW.addUploadFormHandlers(openAddNewWindowButton,addnewWindow,searchandaddbuttonsbar,openSearchWindowButton);
        
        
    
    } // selecteddocumentSearchNameSpace
    selecteddocumentSearchNameSpace();




    

}); // namespace end


