2010-05-22 17 views
8

में जावास्क्रिप्ट के साथ पाठ की सीमा के लिए शैली लागू करें Iphone पर UIWebView में HTML के रूप में कुछ सरल स्टाइल टेक्स्ट प्रदर्शित कर रहा हूं। यह मूल रूप से कभी-कभी मजबूत या जोरदार वाक्यांश के साथ पैराग्राफ की एक श्रृंखला है। रनटाइम पर मुझे पाठ की श्रेणियों के लिए शैलियों को लागू करने की आवश्यकता है।uiwebview

कुछ समान परिदृश्य हैं, जिनमें से एक खोज परिणामों को हाइलाइट कर रहा है। यदि उपयोगकर्ता ने "कुछ" खोजा है, तो मैं शब्द की घटनाओं के पीछे पृष्ठभूमि रंग बदलना चाहता हूं, फिर बाद में मूल पृष्ठभूमि को पुनर्स्थापित करूँगा।

क्या जावास्क्रिप्ट का उपयोग करके टेक्स्ट की श्रेणियों में शैलियों को लागू करना संभव है? इसका एक महत्वपूर्ण हिस्सा शैलियों को अनसेट करने में भी सक्षम है।

अनुवर्ती दो संभावित मार्ग प्रतीत होते हैं। कोई उद्देश्य-सी में कुछ एचटीएमएल को संशोधित करेगा और इसे जावास्क्रिप्ट के माध्यम से कुछ कंटेनर के नए आंतरिक HTML के रूप में पास करेगा। दूसरे को सीधे डोम नोड्स में हेरफेर करने के लिए जावास्क्रिप्ट का उपयोग करना होगा।

मैं एचटीएमएल में हेरफेर कर सकता हूं, लेकिन यह उद्देश्य-सी में थकाऊ लगता है, इसलिए यदि यह एक उचित दृष्टिकोण है तो मैं डीओएम में हेरफेर करूँगा। मैं जावास्क्रिप्ट और डोम से परिचित नहीं हूं इसलिए मुझे नहीं पता कि यह एक उचित दृष्टिकोण है या नहीं।

मैंने ऑफसेट के साथ टेक्स्ट श्रेणियों और नोड श्रेणियों के बीच अनुवाद करने के लिए कुछ दिनचर्या लिखीं। इसलिए यदि मैं टेक्स्ट रेंज 100-200 से शुरू करता हूं और यह एक पैराग्राफ में शुरू होता है और एक तिहाई में समाप्त होता है, तो मैं टेक्स्ट नोड्स और ऑफ़सेट को उन नोड्स के भीतर प्राप्त कर सकता हूं जो दिए गए टेक्स्ट रेंज का प्रतिनिधित्व करते हैं। मुझे टेक्स्ट में ऑफसेट पर टेक्स्ट नोड को विभाजित करने का एक तरीका चाहिए। वर्तमान में मैं पाठ श्रेणी वाले पैराग्राफ में शैलियों को लागू करता हूं।

कुछ नोट:

  • सीधे जावास्क्रिप्ट कृपया, कोई बाहरी jQuery की तरह चौखटे।
  • परिवर्तनों को डिस्क पर कभी भी लिखे जाने की आवश्यकता नहीं है।
  • परिवर्तन पूर्ववत या कम से कम हटाने योग्य होना चाहिए।
  • लागू करने के लिए शैलियों को पहले से ही एक सीएसएस फ़ाइल में मौजूद है।
  • इसे आईफोन 3.0 और आगे काम करने की आवश्यकता है।
  • सभी स्रोत फ़ाइलों को ऐप के साथ भेज दिया जाता है।
  • कृपया वर्बोज़ बनें।

किसी भी सुझाव के लिए धन्यवाद।

उत्तर

19

मुझे लगता है कि आप इसके लिए एक संपूर्ण समाधान प्राप्त करने के लिए बहुत कुछ पूछ रहे हैं, लेकिन यह दिलचस्प लग रहा था इसलिए मैंने इसे लागू किया है। हाल ही में वेबकिट ब्राउज़र में निम्नलिखित काम करता है, जिसमें आईफोन 3.0 पर आईफोन पर सफारी शामिल है। यह Range की गैर-मानक लेकिन सुविधाजनक intersectsNode विधि का उपयोग करता है, जो वेबकिट में मौजूद है लेकिन 3.0 में फ़ायरफ़ॉक्स से हटा दिया गया था, इसलिए यह फ़ायरफ़ॉक्स के हाल के संस्करणों में काम नहीं करता है लेकिन इसे बहुत ही कम करने के लिए किया जा सकता है।

निम्नलिखित प्रत्येक चयनित टेक्स्ट नोड को <span> तत्व के साथ "कुछ क्लास" के वर्ग के साथ घेरेगा और एक अनूठी कक्षा भी आसान पूर्ववत करने की अनुमति देने के लिए होगा। applyClassToSelection इस अद्वितीय कक्षा को लौटाता है; स्पैन को हटाने के लिए इस कक्षा को removeSpansWithClass में पास करें।

अद्यतन: फिक्स्ड समस्या है जब चयन पूरी तरह से एक पाठ नोड

अद्यतन 2 के भीतर निहित है: अब परीक्षण किया और iPhone में काम करता है OS 3.0 चल रहा है।

अद्यतन 3: जोड़ा गया rangeIntersectsNode समारोह फ़ायरफ़ॉक्स 3.0 और बाद के लिए समर्थन जोड़ने के लिए। यह कोड अब फ़ायरफ़ॉक्स 1.0+, सफारी 3.1+, Google क्रोम, ओपेरा 9.6+ और संभवतः अन्य (अब तक अनचाहे) में काम करना चाहिए। यह इंटरनेट एक्सप्लोरर में बिल्कुल भी काम नहीं करता है और उस ब्राउज़र में त्रुटियां देगा। मैं जल्द ही एक आईई संस्करण पर काम करने की योजना बना रहा हूं।

<script type="text/javascript"> 
    var nextId = 0; 

    var rangeIntersectsNode = (typeof window.Range != "undefined" 
      && Range.prototype.intersectsNode) ? 

     function(range, node) { 
      return range.intersectsNode(node); 
     } : 

     function(range, node) { 
      var nodeRange = node.ownerDocument.createRange(); 
      try { 
       nodeRange.selectNode(node); 
      } catch (e) { 
       nodeRange.selectNodeContents(node); 
      } 

      return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 && 
       range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1; 
     }; 

    function applyClassToSelection(cssClass) { 
     var uniqueCssClass = "selection_" + (++nextId); 
     var sel = window.getSelection(); 
     if (sel.rangeCount < 1) { 
      return; 
     } 
     var range = sel.getRangeAt(0); 
     var startNode = range.startContainer, endNode = range.endContainer; 

     // Split the start and end container text nodes, if necessary 
     if (endNode.nodeType == 3) { 
      endNode.splitText(range.endOffset); 
      range.setEnd(endNode, endNode.length); 
     } 

     if (startNode.nodeType == 3) { 
      startNode = startNode.splitText(range.startOffset); 
      range.setStart(startNode, 0); 
     } 

     // Create an array of all the text nodes in the selection 
     // using a TreeWalker 
     var containerElement = range.commonAncestorContainer; 
     if (containerElement.nodeType != 1) { 
      containerElement = containerElement.parentNode; 
     } 

     var treeWalker = document.createTreeWalker(
      containerElement, 
      NodeFilter.SHOW_TEXT, 
      // Note that Range.intersectsNode is non-standard but 
      // implemented in WebKit 
      function(node) { 
       return rangeIntersectsNode(range, node) ? 
        NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; 
      }, 
      false 
     ); 

     var selectedTextNodes = []; 
     while (treeWalker.nextNode()) { 
      selectedTextNodes.push(treeWalker.currentNode); 
     } 

     var textNode, span; 

     // Place each text node within range inside a <span> 
     // element with the desired class 
     for (var i = 0, len = selectedTextNodes.length; i < len; ++i) { 
      textNode = selectedTextNodes[i]; 
      span = document.createElement("span"); 
      span.className = cssClass + " " + uniqueCssClass; 
      textNode.parentNode.insertBefore(span, textNode); 
      span.appendChild(textNode); 
     } 

     return uniqueCssClass; 
    } 

    function removeSpansWithClass(cssClass) { 
     var spans = document.body.getElementsByClassName(cssClass), 
      span, parentNode; 

     // Convert spans to an array to prevent live updating of 
     // the list as we remove the spans 
     spans = Array.prototype.slice.call(spans, 0); 

     for (var i = 0, len = spans.length; i < len; ++i) { 
      span = spans[i]; 
      parentNode = span.parentNode; 
      parentNode.insertBefore(span.firstChild, span); 
      parentNode.removeChild(span); 

      // Glue any adjacent text nodes back together 
      parentNode.normalize(); 
     } 
    } 

    var c; 
</script> 

<input type="button" onclick="c = applyClassToSelection('someclass')" 
    value="Add class"> 
<input type="button" onclick="removeSpansWithClass(c)" 
    value="Remove class"> 
+0

धन्यवाद। यह मेरी अपेक्षा से अधिक है। – drawnonward

+0

शायद इसे गिटूब पर रखें, इसलिए हम कम से कम अनुसरण कर सकते हैं। – Mark

+1

मैं एक क्रॉस-ब्राउज़र रेंज/चयन लाइब्रेरी पर काम कर रहा हूं जिसमें इसका एक बेहतर संस्करण शामिल होगा। अभी तक बहुत प्रगति नहीं हुई है, लेकिन मैंने एक Google Code प्रोजेक्ट बनाया है: http://code.google.com/p/rangy/ –