               /*  .................................................  */
               /*  file: reviewscripts.js                             */
               /*  author:Ted O'Hara                                  */
               /*  purpose: supporting scripts for reviews            */                       
               /*  Created: 12/03/2007                                */
               /*  Copyright (C) 2007 bx.com, Inc.                    */
               /*  .................................................  */ 
               
 function enumerateProperties()
    {
      var pString = this + '\n\nProperties:\n---------------\n';
      for (property in this)
        {
          if (typeof this[property] == 'function') 
            {
              {pString += property + ': (function)\n';}
            }
          else
          
            {pString += property + ': ' + this[property] + '\t\t\tType: ' + typeof this[property] + '\n';}
        }
      return pString
    }
  //Object.prototype.toFullString = enumerateProperties
  
 
   
//~~~~~~Rating functions ~~~~~~~~~~~~~~~~/

//Event handler on the rating stars images 
function setRating()
  {
    var hiddenRatingField = document.getElementById('ratingHidden')
    hiddenRatingField.value = this.rating; //set hidden field
    var filename; //establishing
    var rateImgs = pc_Review.rateImgs
    for (var i = 0; i < rateImgs.length; i++) //loop over star image node list
      {      
        currStar = rateImgs[i]
        if (currStar.rating < this.rating) //lesser rating
          {
            filename = (currStar.className.match(/full/)) ? pc_Review.starImg : pc_Review.halfDotImg //star or blank image, for lesser ratings
          }
        else if (currStar.rating == this.rating) // this one
          {
            filename = (currStar.className.match(/full/)) ? pc_Review.starImg : pc_Review.halfImg //star or "1/2" image for this rating
          }
        else if (currStar.rating > this.rating) //greater rating
          {
            filename = (currStar.className.match(/full/)) ? pc_Review.dotImg : pc_Review.halfDotImg //dot or blank image, for greater ratings
          }
        
       currStar.src =  jsthemeiconpath + filename //set the image src
      }//end, for  
  }//end, function

 // function called after we have saved a review entry
 function handleEntryResponse(responseText)
  {
    var responseObj = evalJSON(responseText)    
    setMessages(responseObj.messages)
    var responseContainer = document.getElementById('reviewEntryMsg')
    if(responseContainer.firstChild) {responseContainer.firstChild.nodeValue = responseObj.returnval}
    else {responseContainer.appendChild(document.createTextNode(responseObj.returnval))}
    var clearFields = ['reviewtitle','rating','review']
    
    if (!responseObj.error) //saved successfully, clear fields and hide form
     {
      for (var c = 0; c < clearFields.length; c++) {pc_Review.entryForm.elements[clearFields[c]].value = ''} //need to clear out fields for Mozilla
      pc_Review.ratingContainer.style.display= 'none'
     }
  }
 
 //function to place messages in the review entry message list. Called by both submitReviewEntry (client side validation) and handleEntryResponse (server side messaging)
 function setMessages(messageArray) 
  {
    var containerUL = document.getElementById('reviewEntryList')
    destroyChildNodes(containerUL)
    for (var i = 0; i < messageArray.length; i++) {createElementAndText(messageArray[i],containerUL,'LI') }
  }
  
 //rollover handlers on helpfulness buttons
 function reviewBtnOn() 
  {
    if(this.type == 'image')
      {
        var srcString = this.src
        if (srcString.match(/_dim/)) {return false}
        srcString = srcString.replace(/.gif/,'_over.gif')  
        srcString = srcString.replace(/_over_over.gif/,'_over.gif')  
        this.src = srcString
      }
    else
      {        
        if (this.className.match(/disabled/)) {return false}
        this.className = (this.className == '') ? 'helpfulOver' : this.className + ' helpfulOver'  
      }    
  }
  
 function reviewBtnOff() 
  {
    if (this.type == 'image')
      {
        var srcString = this.src
        if (srcString.match(/_dim/)) {return false}
        srcString = srcString.replace(/_over.gif/,'.gif')
        this.src = srcString 
      }
    else
      {
        if (this.className.match(/disabled/)) {return false}        
      }    
    
  }
 
 //event handler to validate and submit the review data 
 function submitReviewEntry()
  {    
    var fieldArray = ['reviewtitle','rating','review','productid']
    var messages = pc_Review.entryErrors
    var urlString = '/includes/AJAX/saveProductReview_ajx.cfm?x=z'
    var messageArray = new Array()
    var varValue 
    for (var i = 0; i < fieldArray.length; i++)
      {
        varValue = pc_Review.entryForm.elements[fieldArray[i]].value
        if (varValue == '') {messageArray.push(messages[i])}
        else{urlString += '&' + fieldArray[i] + '=' + encodeURIComponent(varValue)}        
      }    
     if (messageArray.length > 0 ) {setMessages(messageArray) }
     else {submitFormData(urlString,handleEntryResponse)}
     
    return false
  }
  
 //add handlers and properties to the rating images
 function initRatingEntry(containerObj)
  {
    if (containerObj == null) {return false} //container element doesn't exist; bail.
    var ratingContainer = document.getElementById('ratingcontainer_entry')
    var rateImgs  = ratingContainer.getElementsByTagName('IMG')
    var currStar
    for (var i = 0; i < rateImgs.length; i++)
      {      
        currStar = rateImgs[i]
        currStar.rating = parseInt(currStar.id.replace(/rating_/,''))/10;
        currStar.onclick = setRating
      }
    pc_Review.rateImgs = rateImgs
    pc_Review.entryForm = document.getElementById('ratingHidden').form // review form *may* be part of a larger form, so store a reference to it.
    document.getElementById('submitReviewEntry').onclick = submitReviewEntry
    var cancelBtn = document.getElementById('cancelReviewEntry')
    if (cancelBtn != null) {cancelBtn.onclick = function(){togglelayer('pr_RevEntryCntr',0)}}    
  }

  
// ~~~~~~~ Review Functions  ~~~~~~~~~~~~~~~~~
  
function handleUsefulness(responseText)
  {
    //debugResponse(responseText)
    var responseObj = evalJSON(responseText)
    var thisbtn = pc_Review.currentHelpful
    thisbtn.onmouseout = reviewBtnOff //re-enable  mouseout
    thisbtn.onmouseout() //unhighlight 
    if(pc_Review.currentHelpful.textarea) 
      {
        pc_Review.currentHelpful.textarea.value = '' 
        pc_Review.currentHelpful.textarea = null
      }       
   
    //private function to dim the buttons or images
    function dimButtons()
      {        
        var argObj;
        for (var a=0; a < arguments.length; a++)
          {
            argObj = arguments[a]
            switch (argObj.type)
              {
                case 'image': {argObj.src = argObj.src.replace(/.gif/,'_dim.gif'); break;}
                case 'button': {argObj.className = 'buttondisabled' ;break;} 
                case 'radio':  {argObj.disabled = true}           
              }//end, switch   
           
           argObj.onclick = warnAlreadyVoted    
           if (argObj.doComment != null)  
            {
              addClass(thisbtn.doComment,'linkdisabled')
              thisbtn.doComment.onclick = warnAlreadyVoted   
            }
           if (argObj.commentDiv != null) {argObj.commentDiv.style.display = 'none'} 
             
          }//end, for
      }//end, local function    
    
    dimButtons(thisbtn,thisbtn.mate)  
    if (!responseObj.error) // no error, update helpfulness string
      {
        //update score        
        var auxID = thisbtn.id.replace(/reviewHelpful/,'helpflScore')
        auxID = auxID.replace(/_(Y|N)/,'')
        auxID = auxID.replace(/_(best|worst)/,'$1')
        document.getElementById(auxID).firstChild.nodeValue = responseObj.helpfulString; 
        thisbtn.commentDiv.style.display = 'none'    
        
        
      }
     if (responseObj.returnmsg.length)
      {
        var alertStr = "";
        for (var a=0; a < responseObj.returnmsg.length; a++) {alertStr += responseObj.returnmsg[a]}
        alert(alertStr)
      }
    thisbtn.blur()
    pc_Review.currentHelpful = null
  }//end function
  
//~~~~ DIALOG BOX FUNCTIONS ~~~~~~~~
// Cancel the action
function cancelComment()
  {
    pc_Review.currentHelpful.onmouseout = reviewBtnOff //re-enable  mouseout
    pc_Review.currentHelpful.onmouseout() //unhighlight 
    pc_Review.currentHelpful.helplevelfield.value = '';
    if(this.textarea) {this.textarea.value = '';}    
    if(!pc_Review.showCommentEntry) {pc_Review.currentHelpful.commentDiv.style.display = 'none'}
    pc_Review.currentHelpful = null;//clear property
    togglelayer('reviewdialog',0)
  }

//show the comment entry field. 
function enableComment()
  {
    pc_Review.currentHelpful.commentDiv.style.display = ''
    pc_Review.currentHelpful.commentDiv.getElementsByTagName('TEXTAREA')[0].focus();
    togglelayer('reviewdialog',0)
  }

//function to only save the helpfulness vote.  
function saveHelpful()
  {
    submitFormData(pc_Review.urlString,handleUsefulness) 
    pc_Review.urlString = ''; //clear the property
    togglelayer('reviewdialog',0)
  }
  
//Event handler for  the "Was this helpful" controls.    
function submitUsefulness(e)
  {     
    if(! pc_Review.loggedIn) {memberOnly(window.location.search.match(/pid=/)); return false}//setting the "take me back" parameter to know whether the pid is in the url; if it isn't there isn't any point in taking the user back.
    if (!e) e = window.event;
    
    var reviewid = this.id.split('_')[1]
    var helplevel = (this.value == 'Yes') ? 1 : 0
    this.helplevelfield.value = helplevel
    this.onmouseout = null; //force to stay highlighted
    this.mate.onmouseout = reviewBtnOff //re-enable mate's mouseout
    this.mate.onmouseout()
    
    pc_Review.urlString = '/includes/AJAX/saveReviewComment_ajx.cfm?reviewid=' + reviewid + '&helplevel=' + helplevel
    pc_Review.currentHelpful = this
        
    if(pc_Review.allowCommentEntry && !pc_Review.showCommentEntry) //comment entry allowed
      {
        if (this.commentDiv.style.display == 'none')
          {
            var mousePos = getmousepos(e)
            var dialogbox = document.getElementById('reviewdialog');
            dialogbox.style.top = (mousePos.y - pc_Review.dialogOffset) + 'px';
            togglelayer('reviewdialog',1)  
          }        
      
      }
    else {saveHelpful()} //installation only allows usefulness votes.
    
    return false;
  }
  
function saveComment()
  {
    pc_Review.urlString = ''; //clear the property, which had been set previously
    var reviewid = this.id.split('_')[1];
    var helplevel =  this.helplevelfield.value;
    
    pc_Review.currentHelpful.textarea = this.textarea;
    
    var commentText = this.textarea.value;
    var urlString = '/includes/AJAX/saveReviewComment_ajx.cfm?reviewid=' + reviewid + '&helplevel=' + helplevel + '&commentText=' +  encodeURIComponent(commentText)
    
    submitFormData(urlString,handleUsefulness)
  }

  
function warnAlreadyVoted()
  {
    alert('Sorry, you\'ve already rated this review.')
    return false
  }

//function to initialize events in the designated review section. Called initially, and also after importing the section.
function initReviewEvents(containerObj)
  {
    var inputArray = containerObj.getElementsByTagName('INPUT');
    var inputElem, lkElem, auxID, mateid //establishing
    for (var i = 0; i < inputArray.length; i++)//loop over input tags
      {
        inputElem = inputArray[i]
        if(inputElem.name.match(/reviewHelpful/) && !inputElem.disabled)
          {
            inputElem.onclick = (!inputElem.className.match(/disabled/)) ? submitUsefulness : warnAlreadyVoted
            if(inputElem.type != 'radio')
              {
                inputElem.onmouseover = reviewBtnOn;
                inputElem.onmouseout = reviewBtnOff
              }            
            
            auxID = inputElem.id.replace(/reviewHelpful/,'pr_commentEntryDiv')
            auxID = auxID.replace(/_(Y|N)/,'')
            //auxID = auxID.replace(/_(best|worst)/,'$1')
            inputElem.commentDiv = document.getElementById(auxID)
            inputElem.helplevelfield  = document.getElementById(auxID.replace(/pr_commentEntryDiv/,'helplevel'))
            
            if(inputElem.commentDiv != null)
              {
                //submit button for comment entry
                inputElem.commentSubmit = document.getElementById(auxID.replace(/pr_commentEntryDiv/,'submitcomment'))
                inputElem.commentSubmit.onclick = saveComment
                
                //hidden field to record helpfulness vote
                inputElem.commentSubmit.helplevelfield = inputElem.helplevelfield
                inputElem.commentSubmit.textarea = document.getElementById(auxID.replace(/pr_commentEntryDiv/,'pr_commentEntry'))
                //button to cancel helpfulness submission
                inputElem.commentCancel = document.getElementById(auxID.replace(/pr_commentEntryDiv/,'cancelcomment'))
                inputElem.commentCancel.textarea = inputElem.commentSubmit.textarea
                inputElem.commentCancel.onclick = cancelComment;
                
                inputElem.doComment = document.getElementById(auxID.replace(/pr_commentEntryDiv/,'pr_doComment'))
                if (inputElem.doComment.className.match(/linkdisabled/))
                  {
                    inputElem.doComment.onclick = warnAlreadyVoted;
                  }
                else
                  {
                    if (inputElem.id.match(/Y/)) {inputElem.doComment.helpTrigger = inputElem}//tag the comment link to one of the buttons
                    inputElem.doComment.onclick = function(){pc_Review.currentHelpful = this.helpTrigger; enableComment(); return false}
                  }       
              }            
            //get the mate of the current (Y|N) button
            mateid = (inputElem.id.match(/_Y/)) ? inputElem.id.replace(/_Y/,'_N'): inputElem.id.replace(/_N/,'_Y')    
            inputElem.mate = document.getElementById(mateid)
            
          }//end, name match
      }//end, for   
    
    var lkArray = containerObj.getElementsByTagName('A');
    for (var a = 0; a < lkArray.length; a++) //loop over links in review section
      {
       lkElem = lkArray[a]
       if (lkElem.className.match(/pr_getRvw/)) {lkElem.onclick = fetchSingleReview} //Add event handler to get single review (we're truncating them) 
       if (lkElem.className.match(/getRvwCmmt/)) {lkElem.onclick = fetchReviewComments} //Add event handler to get comments for a review 
       if (lkElem.className.match(/pr_doComplaint/)) {lkElem.onclick = function(){newwindow(this.href); return false}} //Pop up the complaint form. I want to take them out of the page for complaints to reinforce seriousness.
      }     
  } //end, function

//remove link from invocation element, leaving only the text  
function removeNestedLink(elem)
  {
    var invokeTextNode = elem.firstChild.firstChild
    elem.removeChild(elem.firstChild)
    elem.appendChild(invokeTextNode)
    elem.onclick = null; //clear the event handler
  }

//~~~ REVIEW ENTRY FORM
//function to get the review entry form via AJAX  
function fetchEntryForm()
  {
    var urlString = '/includes/ProdTemplateInclude/review/enterProductReview.cfm?productid=' + pc_Review.productid
    submitFormData(urlString,insertEntryForm)
    return false
  }

//function to insert the review entry form into the designated place  
function insertEntryForm(responseText)
  {
    var myContainer = document.getElementById('pr_RevEntryCntr')
    myContainer.innerHTML = responseText;
    
    pc_Review.ratingContainer = document.getElementById('productReviewEntry')  
    pc_Review.entryInvoke.onclick = function(){togglelayer('pr_RevEntryCntr',1);return false}
   
    //initialize the inserted form
    initRatingEntry(myContainer)    
  }

  
// ~~~ FETCH AND INSERT COMMENTS ~~~~~~~
function fetchReviewComments()
  {
    var reviewid = this.id.split('_')[2]
    pc_Review.commentContainer = document.getElementById(this.id.replace(/pr_getRvwCmmt/,'viewpr_reviewComment'))
    var urlString = '/includes/ProdTemplateInclude/review/showReviewComments.cfm?reviewid=' + reviewid    
    submitFormData(urlString,insertReviewComments)
    return false
  }
function insertReviewComments(responseText)
  {
    //debugResponse(responseText)
    pc_Review.commentContainer.innerHTML = responseText
  }
  
//~~~ OTHER REVIEWS ~~~~~~
//function to get the other (non best-worst) reviews  
function fetchOtherReviews()
  {
    var urlString = '/includes/ProdTemplateInclude/review/showOtherReviews.cfm?productid=' + pc_Review.productid + '&reviewKeyName=' + pc_Review.reviewKeyName + '&reviewKeyValue=' + pc_Review.reviewKeyValue
    
    urlString += '&pr_startrow=' + this.startRow
    urlString += '&pr_endrow=' + this.endRow
    
    pc_Review.startRow = this.startRow
    pc_Review.endRow = this.endRow
    
    submitFormData(urlString,insertOtherReviews)
    return false
  }

 //inserts the other reviews into the page
function insertOtherReviews(responseText)
  {
    var myContainer = document.getElementById('pr_otherRevCntr')
    myContainer.innerHTML = responseText;
    
    //remove link from invocation element, leaving only the text
    if (pc_Review.otherRvwInvoke.firstChild.nodeType == 1) {removeNestedLink(pc_Review.otherRvwInvoke)}
        
    //pagination 
    if (pc_Review.maxRows < pc_Review.recordCount)
      {        
        var pageArgObj = {startRow:pc_Review.startRow,
                          endRow:pc_Review.endRow,
                          maxRows:pc_Review.maxRows,
                          containerIdRoot:'pr_paginate',
                          totalCount: pc_Review.recordCount,
                          callBackFN:fetchOtherReviews}
        
        createPagination(pageArgObj)  
      }    
    //initialize the inserted form
    initReviewEvents(myContainer)       
  }

//~~~ SINGLE REVIEW ~~~~~~
//function to insert the retrieved single review into place  
function insertSingleReview(responseText)
  {
    var responseObj = evalJSON(responseText)    
    if (responseObj.error) {alert('Sorry, we were unable to retrieve that ' + pc_Review.reviewname + ' at the current time.')}
    else
      {
        pc_Review.singleReviewContainer.innerHTML = responseObj.reviewtext
        initReviewEvents(pc_Review.container)
        pc_Review.singleReviewContainer = null        
      }  
  }
 
//make request to get a single review. Stores location in global pc_Review object 
function fetchSingleReview()
  {
    var reviewid = this.id.split('_')[2]
    var urlString = '/includes/AJAX/getSingleReview_ajx.cfm?reviewid=' + reviewid;
    pc_Review.singleReviewContainer = document.getElementById(this.id.replace(/getRvw/,'reviewContent'))
    submitFormData(urlString,insertSingleReview)
    return false
  }

  
//~~~~ INITIALIZATION ~~~~~~~~~~~~~~~~~~~~~
pc_Review.currentHelpful = null
  
pc_Review.ratingContainer = document.getElementById('productReviewEntry')
initRatingEntry(pc_Review.ratingContainer) //initialize star rating images

initReviewEvents(pc_Review.container)//initialize the controls in the reviews section

pc_Review.entryInvoke = document.getElementById('pr_getRevEntry') //link to fetch the entry form
if (pc_Review.entryInvoke != null) pc_Review.entryInvoke.onclick = fetchEntryForm //if present, add event handler to get it via AJAX (non JS action is to reload page w. form in place)

pc_Review.otherRvwInvoke = document.getElementById('pr_getOtherRev') //link to get the other reviews
if (pc_Review.otherRvwInvoke != null) //if present, add pagination data, and event handler to fetch other reviews via AJAX (non JS action is to reload the page with reviews present)
  {
    pc_Review.otherRvwInvoke.startRow = 1
    pc_Review.otherRvwInvoke.endRow = pc_Review.endRow
    pc_Review.otherRvwInvoke.onclick = fetchOtherReviews
  }
 
var dialogButtonArea = document.getElementById('reviewdialogBtns') //area of dialog box that holds the buttons
if (dialogButtonArea != null)
  {
    var dialogButtons = dialogButtonArea.getElementsByTagName('INPUT')
    dialogButtons[0].onclick = cancelComment //cancel button
    dialogButtons[1].onclick = enableComment //yes button - open up comment area
    dialogButtons[2].onclick = saveHelpful //no button - no comment just save the helpful status
  }

//alert(pc_Review.toFullString())

