2011-08-18 1 views
1

je ferme pas interdomaine une page hébergée dans le domaine « de virtualcasa1 » ouverture d'une boîte de dialogue modale:SharePoint: commonModalDialogClose ne dialogue

var options = { 
    title: "Repro", 
    width: 400, 
    height: 600, 
    url: http://domain2:999/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx //[1] 
    //url: http://virtualcasa1/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx [2] 
}; 
SP.UI.ModalDialog.showModalDialog(options); 

Et je le code pour le fermer:

alert(document.domain); 
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancelled clicked'); 

Si les deux sont dans le même domaine (cas [2] ci-dessus), la boîte de dialogue se ferme bien, pas de problèmes.

Mais -. Si la page cible hébergé dans la boîte de dialogue (cas [1] ci-dessus), boîte de dialogue ne se ferme pas :-(

document.domain montre au-dessus du domaine correct où la page existe

Je soupçonne Je suis face à un problème interdomaine ici (duh), mais comment y remédier ou je me trompe et n'est pas question XDomain liée

Merci beaucoup

Répondre

0

j'ai exactement le même problème?! - une boîte de dialogue ouvrant une page de vue pour un élément fonctionne correctement lorsqu'elle est ouverte à partir d'un site co Cliquez sur la même application/le même domaine Web, mais le bouton Fermer ne fonctionne pas lorsque vous ouvrez le même élément à partir d'une collection de sites hébergée dans une application Web distincte. Je suppose que c'est une chose inter-domaine donc j'ai modifié la solution pour accommoder cette restriction, cependant, je ne suis pas content à 100% car cela rend la solution globale un peu difficile à utiliser pour un utilisateur ... la perspective. J'ai mis le problème de côté pour le moment en raison des délais du projet, mais je suis toujours curieux de savoir pourquoi. La seule chose à laquelle je peux penser est l'ensemble du phénomène inter-domaines qui l'a provoqué et qui est peut-être là pour éviter les failles de sécurité XSS.

3

PostMessage de HTML5 est votre réponse.

https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage

Votre fenêtre parent qui initie la boîte de dialogue doit avoir le javascript suivant:

function listener(event) { 
    //alert(event.data); 
    if (event.data == 'Cancel') { 
    SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancel clicked'); 
    } 
    else { 
    SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, event.data); 
    } 
} 

if (window.addEventListener) { 
    addEventListener("message", listener, false) 
} else { 
    attachEvent("onmessage", listener) 
} 

Javascript pour OK et Annuler dans votre pop-up: de

<input type="button" value="OK" onclick="parent.postMessage('Message to be displayed by the parent', '*');" class="ms-ButtonHeightWidth" /> 
<input type="button" value="Cancel" onclick="parent.postMessage('Cancel', '*');" class="ms-ButtonHeightWidth" /> 
0

Ajay réponse de la Le 1er août 2014 est bien, mais il faut un peu plus d'explications. La raison de l'échec de la fermeture du dialogue est simple. Les fonctionnalités de sécurité des scripts inter-sites des navigateurs modernes interdisent certaines choses, dont l'utilisation de window.frameElement dans la fenêtre encadrée. C'est une propriété en lecture seule sur l'objet window et elle devient null (ou avec IE, elle lève une exception quand vous essayez d'y accéder). Les gestionnaires d'événements Cancel ordinaires dans la boîte de dialogue modale se terminent par un appel à window.frameElement.cancelPopup(). Cela échouera bien sûr. Le gestionnaire d'enregistrement ordinaire où l'enregistrement a fonctionné côté serveur entraîne l'envoi par SharePoint d'une seule ligne en tant que document de remplacement, qui est un scriptlet appelé window.frameElement.commitPopup(). Cela ne fonctionnera pas non plus, et c'est une vraie peine à surmonter car la page a été rechargée et il n'y a aucun script disponible pour gérer quoi que ce soit. XSS ne nous donnera pas accès au DOM encadré à partir de la page d'appel. Pour faire fonctionner un formulaire hébergé inter-domaines de manière transparente, vous devez ajouter un script à la fois à la page qui ouvre la boîte de dialogue et à la page encadrée. Dans la page qui ouvre la boîte de dialogue, vous définissez l'écouteur de message comme suggéré par Ajay.Dans la page sous forme encadrée, vous avez besoin quelque chose comme ci-dessous:

(function() { 
    $(document).ready(function() { 
     var frameElement = null; 
     // Try/catch to overcome IE Access Denied exception on window.frameElement 
     try { 
      frameElement = window.frameElement; 
     } catch (Exception) {} 

     // Determine that the page is hosted in a dialog from a different domain 
     if (window.parent && !frameElement) { 
      // Set the correct height for #s4-workspace 
      var frameHeight = $(window).height(); 
      var ribbonHeight = $('#s4-ribbonrow').height(); 
      $('#s4-workspace').height(frameHeight - ribbonHeight); 

      // Finds the Save and Cancel buttons and hijacks the onclick 
      function applyClickHandlers(theDocument) { 
       $(theDocument).find('input[value="Cancel"]').removeAttr('onclick').on('click', doTheClose); 
       $(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Cancel-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheClose); 
       $(theDocument).find('input[value="Save"]').removeAttr('onclick').on('click', doTheCommit); 
       $(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Publish-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheCommit); 
      } 

      // Function to perform onclick for Cancel 
      function doTheClose(evt) { 
       evt.preventDefault(); 
       parent.postMessage('Cancel', '*'); 
      } 

      // Function to perform onclick for Save 
      function doTheCommit(evt) { 
       evt.preventDefault(); 

       if (!PreSaveItem()) return false; 
       var targetName = $('input[value="Save"]').attr('name'); 
       var oldOnSubmit = WebForm_OnSubmit; 
       WebForm_OnSubmit = function() { 
        var retVal = oldOnSubmit.call(this); 
        if (retVal) { 
         var theForm = $('#aspnetForm'); 
         // not sure whether following line is needed, 
         // but doesn't hurt 
         $('#__EVENTTARGET').val(targetName); 
         var formData = new FormData(theForm[0]); 
         $.ajax(
         { 
          url: theForm.attr('action'), 
          data: formData, 
          cache: false, 
          contentType: false, 
          processData: false, 
          method: 'POST', 
          type: 'POST', // For jQuery < 1.9 
          success: function(data, status, transport) { 
           console.log(arguments); 
           // hijack the response if it's just script to 
           // commit the popup (which will break) 
           if (data.startsWith('<script') && 
            data.indexOf('.commitPopup()') > -1) 
           { 
            parent.postMessage('OK', '*'); 
            return; 
           } 

           // popup not being committed, so actually 
           // submit the form and replace the page. 
           theForm.submit(); 
          } 
         }).fail(function() { 
          console.log('Ajax post failed.'); 
          console.log(arguments); 
         }); 
        } 

        return false; 
       } 
       WebForm_DoPostBackWithOptions(
        new WebForm_PostBackOptions(targetName, 
               "", 
               true, 
               "", 
               "", 
               false, 
               true) 
       ); 
       WebForm_OnSubmit = oldOnSubmit; 
      } 

      applyClickHandlers(document); 
     } 
    }); 
})(); 

Cette solution utilise la bibliothèque jQuery, que notre organisation utilise abondamment. C'est notre cadre préféré (choisi par moi). Je suis sûr que quelqu'un de très intelligent pourrait réécrire cela sans cette dépendance, mais c'est un bon point de départ. J'espère que quelqu'un le trouvera utile, car cela représente un bon travail de deux jours. Certaines choses à noter:

SharePoint effectue une publication sur toutes sortes d'événements sur la page, y compris la mise en page en mode édition. Pour cette raison, il est plus logique d'intercepter les clics de bouton spécifiques, à la fois sur le formulaire et dans le ruban, plutôt que de redéfinir en gros, par exemple, la fonction WebForm_OnSubmit globale. Nous écrasons brièvement cela lors d'un clic Enregistrer, puis nous le réinitialisons.

Lors de tout événement de clic sur Enregistrer, nous annulons l'enregistrement normal du formulaire et le remplaçons par une requête POST identique utilisant AJAX. Cela nous permet de rejeter le scriptlet renvoyé lorsque le formulaire a été posté avec succès. Lorsque la soumission du formulaire a échoué, peut-être en raison des valeurs obligatoires vides, nous publions le formulaire correctement pour permettre la mise à jour de la page. C'est bien, puisque le formulaire n'aura pas été traité. Une version antérieure de cette solution prenait le document HTML résultant et remplaçait tout le contenu de la page, mais Internet Explorer n'aime pas cela. L'API FormData nous permet de post the form as multipart-mime. Cette API a au moins un support de base dans tous les navigateurs modernes, et il existe des solutions de contournement pour les plus anciens.

Une autre chose qui semble échouer dans la boîte de dialogue hébergée inter-domaines est le défilement de la fenêtre de contenu. Pour une raison quelconque, la hauteur n'est pas définie correctement sur la div avec l'espace de travail id s4, donc nous avons également mis cela dans la solution.

EDIT: Presque oublié. Vous devrez peut-être ajouter ce contrôle à votre page ASPX encadrée, ce qui peut être fait avec SharePoint Designer:

< WebPartPages: AllowFraming runat = "server"/>

Questions connexes