



// 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 PERSON_EDIT_VIEW = {

    initialize : function() {
        // The currently selected language.
        PERSON_EDIT_VIEW.language = $("#languageholder").attr("class");
        
        PERSON_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(PERSON_EDIT_VIEW.onAjaxStart);
        $("body").ajaxStop( PERSON_EDIT_VIEW.onAjaxStop);        
    }

    /* 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() {
        PERSON_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( PERSON_EDIT_VIEW.postJSONQueue.length > 0 ) {
            ajaxparams = PERSON_EDIT_VIEW.postJSONQueue.shift();
            jQuery.ajax(ajaxparams);
        } else {
            PERSON_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
        PERSON_EDIT_VIEW.postJSONQueue.push(options);
        // If no ajax-call is currently pending, send the request at once. (Otherwise the
        // request will be sent by PERSON_EDIT_VIEW.onAjaxStop()
        if( ! PERSON_EDIT_VIEW.anAjaxRequestIsPending ) {
            options = PERSON_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("curriculumvitaes") ) {
            /* no limut. The user is only allowed to select one CV for each language anyway */
            limit = -1;
        }
        
        if( divElement.hasClass("utvalgte_publikasjoner") ) {
            limit = 20;
        }
        
        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) {
        var header = $("div.avsluttedeprosjekter h4");
        //debugger;
        //header.css("background-image",'url("http://www.ssb.no/gifs/gronn_px9.gif"');
        $("div.visavsluttedeprosjekter").slideUp(1000);
        $("div.avsluttedeprosjekter").slideDown(1000,  
            function() {
                 SET_MIDDLE_COLUMN_HEIGHTS.equalHeight(); // Trigger the equalHeight()-function in the "setmiddlecolheights.js" script, so that the 
                                                          // left and right columns gets resized.
                  
//        header.addClass("person_view_heading");
            }
            );
    
        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':PERSON_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();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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 cvUploadButton = $("button.cvUploadbutton",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
            cvUploadButton.removeAttr("disabled");
        }
        
        
        function onOpenAddNewWindowButton(event) {
            var cvFileToUpload = $("input.cvFileToUpload",addnewWindow);
            cvFileToUpload.val("");
            // disable the upload-button. It will be enabled once the user selects a file.
            cvUploadButton.attr("disabled","disabled");
            searchandaddbuttonsbar.slideUp(500);
            
            //$.scrollTo("+=200px",500);
            addnewWindow.slideDown(500);//, function() {$.scrollTo(addnewWindow_bottom,500);} );
            cvFileToUpload.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 curriculum vitaes. 
        // 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 cvFileToUpload = $("input.cvFileToUpload",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 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 + '" >');
                }
                return form;
                };
        
            // temporarily disable the upload-button, so that the user cannot spam the server by clicking it 
            // repeatedly
            cvUploadButton.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 : PERSON_EDIT_VIEW.formPostURL, 
                    secureuri:false,
                    fileElementId:cvFileToUpload.attr("id"),
                    dataType: 'raw',
                    success: function (data, status)
                    {
                        jQuery.uploadHttpData = oldUploadHttpData;
                        jQuery.createUploadForm = oldCreateUploadForm;
                        loadingimg.hide();
                        cvUploadButton.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 updateCurriculumVitaeList() function understands.
                        PERSON_EDIT_VIEW.updateCurriculumVitaeList({'newline':data});
                        onCloseAddNewWindowButtonClicked(undefined);
                    },
                    error: function (data, status, e)
                    {
                        jQuery.uploadHttpData = oldUploadHttpData;
                        jQuery.createUploadForm = oldCreateUploadForm;
                        loadingimg.hide();
                        cvUploadButton.removeAttr("disabled");
                        humanMsg.displayMsg("Failed to upload the file!");
                        alert(e);
                    }
                };
                
            $.ajaxFileUpload(ajavFileUploadParams);                
            return false;
        }  
        
        
        cvUploadButton.click(ajaxFileUpload)
    }
    
    
    
    , updateCurriculumVitaeList : function(response) {
        var curriculumvitaes = $("div.curriculumvitaes");
        var ulElement = $("ul.curriculumvitae",curriculumvitaes);
        var newline = response['newline'];
        if( newline ) {
            newline = $(newline);
            ulElement.append(newline);      
            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(newline);
            PERSON_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.
    /***********************************************************************************************/
    ,addPublicationOrCVLineHandlers : function(liElement) {
        var liElement = $(liElement);
        var isCVLine = liElement.hasClass("utvalgte_curriculumvitaeer");
        
        var associationMoveUpButton = $(".associationmoveupbutton",liElement);
        associationMoveUpButton.click(PERSON_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(PERSON_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(PERSON_EDIT_VIEW.onAssociationDeleteButton);
        
        var languagecheckboxes = $("input.languagecheckbox",liElement);
        if( isCVLine ) {
            languagecheckboxes.click(PERSON_EDIT_VIEW.onExclusiveLanguageCheckBox);
        } else {
            languagecheckboxes.click(PERSON_EDIT_VIEW.onLanguageCheckBox);
        }
        
        var openreplacewindowbutton = $("button.openreplacewindow",liElement);
        if( openreplacewindowbutton != undefined ) {
            var replacewindow = $("div.replacewindow",liElement);
            PERSON_EDIT_VIEW.addUploadFormHandlers(openreplacewindowbutton,replacewindow);
        }
        //$("button.cancel",replacewindow).click(PERSON_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;
            }
        });
        
        PERSON_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.utvalgte_publikasjoner");
        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);
            PERSON_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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.
                                                             PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(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.utvalgte_publikasjoner");
                                                            if(nextElement.length == 0){
                                                                $(".associationmovedownbutton",prevElement).attr("disabled","disabled");
                                                            }
                                                            PERSON_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.
                                                            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(liElement);
                                                            PERSON_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':PERSON_EDIT_VIEW.language
                         };
        data['operation'] = 'swapassociationorder';
        
        
        var nextElement = liElement.next("li.utvalgte_publikasjoner");
        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);
            PERSON_EDIT_VIEW.setEvenAndOddClasses(liElement.parent());
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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.
                                                            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(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.utvalgte_publikasjoner");
                                                            if(prevElement.length == 0){
                                                                $(".associationmoveupbutton",nextElement).attr("disabled","disabled");
                                                            PERSON_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.
                                                            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(liElement);
                                                            PERSON_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':PERSON_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();
        

        PERSON_EDIT_VIEW.postJSON({ url : PERSON_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)
    {
        PERSON_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");
        
        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':PERSON_EDIT_VIEW.language
                         };
        data['operation'] = 'deleteassociation';
        
        var loadingimg = liElement.parent().siblings().filter(".loadingimg");
        loadingimg.show();
        liElement.slideUp(1000);
        var ulElement = liElement.parent();
        PERSON_EDIT_VIEW.setEvenAndOddClasses(ulElement);
        
        var topicserial = button.parent().attr("ztm:topicserial");
        var selector = "#topic_" + topicserial.replace(/\./g,"\\.");
        var searchResultLinks = $(selector);
        
        PERSON_EDIT_VIEW.postJSON({ url : PERSON_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 CVs.
                                                             searchResultLinks.removeClass("selectedTopic");
                                                             
                                                             loadingimg.hide();
                                                             liElement.remove(); // permanently delete the element
                                                             PERSON_EDIT_VIEW.setEvenAndOddClasses(ulElement);
                                                             
                                                             PERSON_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.
                                                             PERSON_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() {
           PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(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);
            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(newline);        
            PERSON_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.
            
            PERSON_EDIT_VIEW.hideOrShowAssocControlsIfNeeded(ulElement);
        }

        function getSearchResultTitle(isSelected) {
            if( PERSON_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':PERSON_EDIT_VIEW.language,
                        'operation': createassociationOperation,
                        'tm_serial':tm_serial
                        }
            
            var loadingimg = event_target.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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':PERSON_EDIT_VIEW.language,
                        'operation': operation,
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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': PERSON_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();

            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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);        
            }
        }
        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':PERSON_EDIT_VIEW.language,
                        'operation': 'createpublicationlink',
                        'title':addnewTitleTextCtrl.val(),
                        'url':addnewURLTextCtrl.val(),
                        'description':addnewDescriptionTextCtrl.attr("value")
                        }
            
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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() {
    PERSON_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(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(PERSON_EDIT_VIEW.onVisAvsluttedeProsjekterClicked);
    $("a.skjulavsluttedeprosjekter").click(PERSON_EDIT_VIEW.onSkjulAvsluttedeProsjekterClicked);

    // Add the eventhandler for the show/hide additinalimages link.
    $("a.showadditionalimages").click(PERSON_EDIT_VIEW.onShowAdditionalImagesClicked);
    $("a.hideadditionalimages").click(PERSON_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: The description and the homepage url. Both of these fields are stored
    // as occurrences on the persontopic. The occurrences are scoped on the currently selected language.
    /***********************************************************************************************/
    // Get the "Save"-buttons. This 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);
        }*/
        
    }
    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;

        PERSON_EDIT_VIEW.postJSON({ url : PERSON_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) {
       PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(this);
    });
    $("li.utvalgte_curriculumvitaeer").each(function(index) {
       PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(this);
    });
    
    if( editmode.length ) {
        //We use a negative margin-top, to push the "norsk engelsk" header-line a bit up.
        $("div.curriculumvitaes").css("margin-top","-1em"); 
        $("div.utvalgte_publikasjoner").css("margin-top","-1em"); 
            
    }
    
    
    var forskningsfelterDiv = $("div.forskningsfelter");
    var forskningsfelterUL = $("ul.forskningsfelter",forskningsfelterDiv)
    PERSON_EDIT_VIEW.addSearchAndAddHandlers(forskningsfelterDiv,forskningsfelterUL, 
                                             "researchfield_createassociation",
                                             {  "this topic"  :"this research field"
                                               ,"dette emnet" :"dette forskningsfeltet"
                                             }
                                             );
    


    PERSON_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);
            PERSON_EDIT_VIEW.addPublicationOrCVLineHandlers(newline);        
            PERSON_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.
            
            PERSON_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();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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();
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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();

            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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);        
            }
        }
        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();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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 curriculumvitaeSearchNameSpace(){
        /***********************************************************************************************/
        // Handlers for the "search for curriculumvitae" controls.
        /***********************************************************************************************/
        var curriculumvitaes = $("div.curriculumvitaes");
        var associationcontrols    = $("div.associationcontrols",curriculumvitaes);
        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': 'cv_createassociation',
                        'tm_serial':tm_serial
                        }
            
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_EDIT_VIEW.formPostURL
                    , data: data
                    , success: function(response,status) { ;
                                                 PERSON_EDIT_VIEW.updateCurriculumVitaeList(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': 'cv_search',
                        'query':searchTextCtrl.val(),
                        'page': currentpage,
                        'sort': currentsortkey,
                        'reversed': sortreversed
                        }        
            var loadingimg = searchandaddbuttonsbar.siblings().filter(".loadingimg");
            loadingimg.show();
            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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': 'cv_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();

            PERSON_EDIT_VIEW.postJSON({ url : PERSON_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);        
            }
        }
        searchTextCtrl.keydown(onSearchTextCtrlKeyDown);
        
        
        
        
        
        /***********************************************************************************************/
        // Handlers for the "add new cv" controls.
        /***********************************************************************************************/
        PERSON_EDIT_VIEW.addUploadFormHandlers(openAddNewWindowButton,addnewWindow,searchandaddbuttonsbar,openSearchWindowButton);
        
        
    
    } // curriculumvitaeSearchNameSpace
    curriculumvitaeSearchNameSpace();




    

}); // namespace end

