2017-10-02 3 views
0

J'ai une application dans laquelle un générateur de pages crée une page de démarrage enregistrée dans la base de données. L'information sauvegardée est juste le outerHTML de l'objet DOM. Pour créer la fonction d'édition, j'ai besoin d'une fonction inverse qui recrée l'objet DOM hors des informations HTML. Malheureusement, l'affectation des informations décryptées à la section outerHTML n'a aucun résultat, car les modifications de l'objet DOM sont ignorées.Comment extraire un texte HTML d'un objet DOM

Ma question: Comment est-ce que je peux recréer un objet DOM à partir d'informations externes HTML sauvées? Si c'est impossible, quelle serait la bonne façon de faire une telle chose?

EDIT Merci pour votre réponse! Voici quelques extraits de code qui montrent ce que je fais. Le prototype MainWidget obtient des informations de la page HTML & veut attribuer les informations. Les fonctions utilisées font partie d'un autre objet (prototype) appelé Widgets.

var asserts = new Asserts(); 
var calls = new Calls(); 
var constants = new MainConst(); 
var strings = new Strings(); 
var widgets = new MainWidget(); 

MainWidget.method('assign2Widget', function (call, label, value, isValid) { 
    isValid = toBoolean(isValid), value = strings.toString(value); 

    if (calls.isValid(call) && strings.hasMinimalLength(label, 2)) { 
     var section = (!label.includes('Builder') // A marker, not an element! 
         && !label.includes(constants.NewsTicker)) 
      ? widgets.getSgSectionByLabel(document, label) 
      : null; 
     value = strings.decode(decodeURIComponent(value));  //<<<< Code decoded from DB 

     if (asserts.isObject(section)) { 
      section.outerHTML = value; 
     } else if (label.includes(constants.Elements)) { 
      if (asserts.isValid(infos.Elements) && infos.Elements.length > 0) { 
       // HERE, THE CODE FROM DB SHOULD BE ADDED TO WIDGET. 
       // The "label" gives the label of the widget, and the "value" is 
       // what is to be assigned to. 
      } 
     } else if (label.includes(constants.NewsTicker)) { 
      […] 
     } 
     […] 
}); 

Widget.method('getElementTypeByLabel', function (thing, elementType, label) { 
    if (asserts.isObject(thing) 
     && strings.hasMinimalLength(elementType, 2) 
     && strings.hasMinimalLength(label, 2)) { 

     var element, elements = document.getElementsByTagName(elementType); 

     if (asserts.isValid(elements) 
      && asserts.isDefined(elements.length) && elements.length === 0) { 

      elements = thing.children; 
     } 
     for (var i = 0; asserts.isDefined(elements.length) && i < elements.length; i++) { 
      element = elements*; 

      if (element.getAttribute !== null) { 
       var labelName = element.getAttribute(constants.label); 

       if (label === labelName && element !== null) { 
        return element; 
       } 
      } else { 
       return null; 
      } 
     } 
     // If the element was not found, search recursively the elements! 
     for (var i = 0; asserts.isDefined(elements.length) && i < elements.length; i++) { 
      return this.getElementTypeByLabel(elements*, elementType, label); 
     } 
    } else { 
     // Error! //messages.invalidFunctionCall(functionName); 
    } 
    return null; 
}); 

Widget.method('getSgSectionByLabel', function (element, label) { 
    return this.getElementTypeByLabel(element, 'sg-section', label); 
}); 

EDIT 2: J'utilisé que les modifications effectuées dans le sg-section pour recréer le contenu lors de la modification d'une page existante.

MainWidget.js: 
[…] 
MainWidget.method('assign2Widget', function (call, label, value, isValid) { 
    isValid = toBoolean(isValid), value = strings.toString(value); 

    if (calls.isValid(call) && strings.hasMinimalLength(label, 2)) { 
     var section = (!label.includes('Builder') // A marker, not an element! 
         && !label.includes(constants.NewsTicker)) 
      ? widgets.getSgSectionByLabel(document, label) 
      : null; 
     value = strings.decode(decodeURIComponent(value)); 

     if (asserts.isObject(section)) { 
      section.outerHTML = value; 
     } else if (label.includes(constants.Elements)) { 
      if (asserts.isString(value) && value.includes(LeftBracket)) { 
       value = arrays.toArray(value); //value.replace(LeftBracket, '').split(RightBracket); 
      } 
      if (arrays.isArray(value)) { 
       for (var i = 0; i < value.length; i++) { 
        infos.insertGridItem(value[i]); 
       } 
      } 
      […] 

MainInfos.js: 
[…] 
function MainInfos() { 
    this.Elements;      // Object for startGridGenerator 
    this.insertGridItem;    // Function of startGridGenerator 
    this.PrototypeName = 'MainInfos'; 
} 

MainInfos.inherits(Infos); 

MainWidget.method('assign2Widget', function (call, label, value, isValid) { 
    isValid = toBoolean(isValid), value = strings.toString(value); 

    if (calls.isValid(call) && strings.hasMinimalLength(label, 2)) { 
     var section = (!label.includes('Builder') // A marker, not an element! 
         && !label.includes(constants.NewsTicker)) 
      ? widgets.getSgSectionByLabel(document, label) 
      : null; 
     value = strings.decode(decodeURIComponent(value)); 

     if (asserts.isObject(section)) { 
      section.outerHTML = value; 
     } else if (label.includes(constants.Elements)) { 
      if (asserts.isString(value) && value.includes(LeftBracket)) { 
       value = arrays.toArray(value); //value.replace(LeftBracket, '').split(RightBracket); 
      } 
      if (arrays.isArray(value)) { 
       for (var i = 0; i < value.length; i++) { 
        infos.insertGridItem(value[i]); 
       } 
      } 
     } else if (label.includes(constants.NewsTicker)) { 
      […] 
     } 
}); 

startGridGenerator.js: 
[…] 
(function() { 
    var moduleName = 'ivmGridBuilder'; 

    var controllerName = moduleName + Controller; 

    angular.module(moduleName, [ 
     'ionic', 
     'ui.sortable', 
     'ivmColorpicker', 
     'ivmIconpicker' 
    ]) 
     .controller(controllerName, function ($scope, 
               $ionicScrollDelegate, 
               $ionicModal, 
               $sce, 
               CommunicationService) { 
      […] 
      /** 
      * Inserts an existing grid item to the item's array 
      * 
      * @param item 
      */ 
      $scope.insertGridItem = function (item) { 
       if (asserts.isObject(item)) { 
        $scope.items.push(item); 
        infos.Elements.push(item); 
        $ionicScrollDelegate.resize() 
       } else { 
        // First call with no valid item & "remember" this function 
        // by having a link to in in object MainInfos! 
        infos.insertGridItem = $scope.insertGridItem; 
       } 
      }; 

Répondre

1

La solution devrait être comme, vous obtenez la chaîne HTML avec le contenu. Ensuite, vous utilisez le $sce.trustAsHtml(); et l'affecter à une variable de portée qui assurera la sécurité du code HTML. Vous pouvez ensuite utiliser le code HTML ci-dessous qui contient la directive ng-bind-html pour rendre HTML String comme HTML réel.

Voici un exemple de travail de la même chose.

var app = angular.module("angularApp", []); 
 
app.controller("appController", function($scope, $sce) { 
 
    $scope.content = "This text is <em>html capable</em> meaning you can have <a href=\"#\">all</a> sorts <b>of</b> html in here."; 
 
    $scope.output = $sce.trustAsHtml($scope.content); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<h2>Rendering HTML with angularJS</h2> 
 
<div ng-app="angularApp" ng-controller="appController"> 
 
    <div ng-bind-html="output"></div> 
 
</div>

Une autre option est d'utiliser ng-sanitize.

Si vous utilisez ng-sanitize - Les entrées sont nettoyées en analysant le code HTML en jetons. Tous les jetons sécurisés (provenant d'une liste blanche) sont ensuite remis en série vers une chaîne html correctement échappée. Cela signifie qu'aucune entrée dangereuse ne peut entrer dans la chaîne renvoyée.

Reportez-vous à la question ci-dessous pour une explication plus détaillée.

SO Answer


var app = angular.module("angularApp", ['ngSanitize']); 
 
app.controller("appController", function($scope) { 
 
    $scope.content = "This text is <em>html capable</em> meaning you can have <a href=\"#\">all</a> sorts <b>of</b> html in here."; 
 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.6/angular.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.6/angular-sanitize.min.js"></script> 
 
<h2>Rendering HTML with angularJS</h2> 
 
<div ng-app="angularApp" ng-controller="appController"> 
 
    <div ng-bind-html="content"></div> 
 
</div>

Comme on le voit dans l'exemple ci-dessus il n'y a pas besoin d'appeler $sce.trustAsHtml(); depuis ngSanitize prendra en charge automatiquement. Faites-moi savoir si cette approche vous aide, ou si vous rencontrez des problèmes avec la même chose!

1

Vous pouvez utiliser DOMParser() pour créer un #document ou un élément <template> pour créer une #document-fragment d'une chaîne

const parser = new DOMParser(); 
const doc = parser.parseFromString(/* outerHTML */, "text/html"); 
+0

Merci! J'essaierai si je peux l'utiliser pour remplacer l'objet 'sg-section' vide dans le DOM par les informations' sg-section' '' '' '' '' '' '' '' '' '' '' '' '' '' \ '' '' 'HTHTML''} sauvegardées. – Sae1962

1

Vous pouvez ajouter la chaîne dans une division cachée en page, puis obtenir avec javascript la éléments que vous voulez de cette Div. Comme dans ce code:

var str ='abc 123<div id="test">coursesweb.net</div><span class="cls">some text</span>'; 
document.querySelector('body').insertAdjacentHTML('beforeend', '<div style="display:none;">'+str+'</div>'); 
var ob_test = document.getElementById('test'); 
alert(ob_test.innerHTML); 
+0

Merci pour votre réponse! J'ai un objet appelé 'sg-section' qui est créé par le générateur de page, que je sauvegarde dans la base de données. Est-il possible de changer l'objet vide existant avec celui de la base de données en utilisant l'astuce d'un élément caché? – Sae1962

+0

Essayez ceci: 'document.querySelector ('# sg-section_id'). OuterHTML = 'Chaîne html';'. Ou, si sg-section est un objet dans JS: 'sg-section.outerHTML = 'chaîne html';' – CoursesWeb

+0

Merci pour vos réponses! Je me suis demandé s'il valait mieux sauvegarder un 'sg-section' entier ou simplement le contenu modifié et utiliser ce dernier pour que je n'aie enregistré que l'objet JavaScript. – Sae1962