দিক অনুপাত অনুমান ব্যতীত কীভাবে আইফ্রেমে প্রতিক্রিয়াশীল করবেন?


14

একটি অনুপাত অনুপাত না করে কীভাবে আইফ্রেমে প্রতিক্রিয়াশীল করবেন? উদাহরণস্বরূপ, সামগ্রীটির কোনও প্রস্থ বা উচ্চতা থাকতে পারে যা রেন্ডারিংয়ের আগে অজানা।

দ্রষ্টব্য, আপনি জাভাস্ক্রিপ্ট ব্যবহার করতে পারেন।

উদাহরণ:

<div id="iframe-container">
    <iframe/>
</div>

এটি আকার iframe-container যাতে এর সামগ্রীগুলি অতিরিক্ত স্থান ব্যতীত সবে সজ্জিত হয়, অন্য কথায়, সামগ্রীর জন্য পর্যাপ্ত জায়গা রয়েছে তাই এটি স্ক্রোলিং ছাড়া দেখানো যেতে পারে, তবে বাড়তি কোনও স্থান নেই। ধারক পুরোপুরি iframe মোড়ানো।

এটি দেখায় যে কীভাবে আইফ্রেমে প্রতিক্রিয়াশীল করা যায়, অনুমান করে বিষয়বস্তুর অনুপাত 16: 9 is তবে এই প্রশ্নে, অনুপাতটি পরিবর্তনশীল।


1
আমি @ ট্র্যাভিসজে
বলি

2
ইফ্রেমে সামগ্রীর মাত্রাগুলি গণনা করা সম্ভব, তবে কীভাবে এটি করা উচিত, তা বিষয়বস্তুর উপর কিছুটা নির্ভর করে এবং প্রচুর ব্যবহৃত সিএসএস (একেবারে অবস্থানযুক্ত সামগ্রীটি পরিমাপ করা অত্যন্ত কঠিন)। আপনি যদি কোনও সিএসএস রিসেট ফাইল ব্যবহার করেন তবে ফলাফলটি পুনরায় সেট করা ফাইলটি ব্যবহৃত হয় না এমন পৃষ্ঠার থেকে পৃথক হয় এবং ব্রাউজারগুলির মধ্যেও পরিবর্তিত হয়। Iframe এবং এর পিতামাতার আকার নির্ধারণ করা তুচ্ছ। সুতরাং, পৃষ্ঠার স্টাকচার সম্পর্কে আমাদের আরও বেশি প্রয়োজন, বিশেষত ব্যবহৃত সিএসএস রিসেট ফাইল (গুলি) এর নাম (গুলি) বা আসল সিএসএস, যদি আপনি কোনও সাধারণ ফাইল (গুলি) ব্যবহার করেন না।
তিমু

2
আইফ্রেমে লোড হওয়া দস্তাবেজের উপর কি আপনার নিয়ন্ত্রণ রয়েছে? আমি বলতে চাইছি, আপনি যদি না করেন তবে আপনার করার মতো কিছুই নেই। আইফ্রেমে ডকুমেন্টের ভিতরে (বা সেই দস্তাবেজটি অ্যাক্সেসের মাধ্যমে) সবকিছুই করাতে হবে, অন্যথায় দেখা যায় এটি মোটেই সম্ভব নয়।
টিমু

1
না, তাহলে এটি সম্ভব নয়, বিকাশকারী.মোজিলা.অর্গ.ইন- ইউএস / ডকস / ওয়েব / সুরক্ষা দেখুন … সুরক্ষার কারণে মূল পৃষ্ঠাটি আইফ্রেমে (এবং তদ্বিপরীত) ক্রস-ডোমেন ডকুমেন্ট অ্যাক্সেস করতে পারে না, যদি কেবল আইফ্রেমে প্রদর্শিত ডকুমেন্টের উপর আপনার নিয়ন্ত্রণ থাকে তবেই এটি নিষ্ক্রিয় করা যাবে।
তীমু

1
... 15 বছরের ইন্টারনেট বলা কি যথেষ্ট অসম্ভব? আমাদের কি সত্যিই এই সম্পর্কে একটি নতুন প্রশ্ন প্রয়োজন?
কাইদো

উত্তর:


8

জাভাস্ক্রিপ্ট ব্যবহার করে কোনও ভিন্ন উত্সের আইফ্রেমের সাথে আলাপচারিতা সম্ভব নয় যাতে এর আকার পেতে পারে; এটি করার একমাত্র উপায় হ'ল ব্যবহার করাwindow.postMessage সঙ্গে targetOriginআপনার ডোমেনে সেট বা wildchar *আইফ্রেম উৎস থেকে। আপনি বিভিন্ন উত্সের সাইটগুলি এবং ব্যবহারের সামগ্রীগুলি প্রক্সি করতে পারেন srcdocতবে এটি হ্যাক হিসাবে বিবেচিত এবং এটি এসপিএ এবং আরও অনেক গতিশীল পৃষ্ঠাগুলির সাথে কাজ করবে না।

একই উত্স iFrame আকার

ধরা যাক, আমাদের দুটি একই উত্সের আইফ্রেম রয়েছে, একটি ছোট উচ্চতা এবং স্থির প্রস্থ:

<!-- iframe-short.html -->
<head>
  <style type="text/css">
    html, body { margin: 0 }
    body {
      width: 300px;
    }
  </style>
</head>
<body>
  <div>This is an iFrame</div>
  <span id="val">(val)</span>
</body>

এবং একটি দীর্ঘ উচ্চতা আইফ্রেম:

<!-- iframe-long.html -->
<head>
  <style type="text/css">
    html, body { margin: 0 }
    #expander {
      height: 1200px; 
    }
  </style>
</head>
<body>
  <div>This is a long height iFrame Start</div>
  <span id="val">(val)</span>
  <div id="expander"></div>
  <div>This is a long height iFrame End</div>
  <span id="val">(val)</span>
</body>

আমরা loadব্যবহার iframe.contentWindow.documentকরে প্যারেন্ট উইন্ডোতে প্রেরণ করব তা ব্যবহার করে আমরা ইভেন্টে আইফ্রেম আকার পেতে পারিpostMessage :

<div>
  <iframe id="iframe-local" src="iframe-short.html"></iframe>
</div>
<div>
  <iframe id="iframe-long" src="iframe-long.html"></iframe>
</div>

<script>

function iframeLoad() {
  window.top.postMessage({
    iframeWidth: this.contentWindow.document.body.scrollWidth,
    iframeHeight: this.contentWindow.document.body.scrollHeight,
    params: {
      id: this.getAttribute('id')
    }
  });
}

window.addEventListener('message', ({
  data: {
    iframeWidth,
    iframeHeight,
    params: {
      id
    } = {}
  }
}) => {
  // We add 6 pixels because we have "border-width: 3px" for all the iframes

  if (iframeWidth) {
    document.getElementById(id).style.width = `${iframeWidth + 6}px`;
  }

  if (iframeHeight) {
    document.getElementById(id).style.height = `${iframeHeight + 6}px`;
  }

}, false);

document.getElementById('iframe-local').addEventListener('load', iframeLoad);
document.getElementById('iframe-long').addEventListener('load', iframeLoad);

</script>

আমরা উভয় আইফ্রেমে যথাযথ প্রস্থ এবং উচ্চতা পাব; আপনি এটি এখানে অনলাইনে চেক করতে পারেন এবং এখানে স্ক্রিনশটটি দেখতে পারেন

বিভিন্ন উত্স আইফ্রেম আকার হ্যাক ( হয়নি )

এখানে বর্ণিত পদ্ধতিটি হ্যাক এবং এটি ব্যবহার করা উচিত যদি এটি একেবারে প্রয়োজনীয় এবং আশেপাশে অন্য কোনও উপায় না থাকে; এটি বেশিরভাগ গতিশীল উত্পন্ন পৃষ্ঠাগুলি এবং এসপিএগুলির জন্য কাজ করবে না । পদ্ধতিটি কর্স নীতিকে বাইপাস করতে একটি প্রক্সি ব্যবহার করে পৃষ্ঠার এইচটিএমএল উত্স কোডটি আনে (cors-anywhere এটি একটি সাধারণ সিওআরএস প্রক্সি সার্ভার তৈরি করার একটি সহজ উপায় এবং এটিতে একটি অনলাইন ডেমো রয়েছেhttps://cors-anywhere.herokuapp.com ) এটি তখন জেএস কোডটিকে সেই এইচটিএমএলকে ইনজেকশন দেয় postMessageএবং এর আকারটি প্রেরণ করতে পারে মূল নথিতে আইফ্রেম। এমনকি এটি আইফ্রেমে resize( আইফ্রেমের সাথে মিলিতwidth: 100% ) ইভেন্ট পরিচালনা করে এবং আইফ্রেম আকারটি পিতামাতার কাছে পোস্ট করে।

patchIframeHtml:

আইফ্রেম এইচটিএমএল কোডটি প্যাচ করার জন্য একটি ফাংশন এবং কাস্টম জাভাস্ক্রিপ্ট ইনজেক্ট postMessageকরার জন্য যা আইফ্রেম আকারটি পিতামাতার কাছে প্রেরণে ব্যবহার করবেload এবং এর resize। যদি originপ্যারামিটারের জন্য কোনও মান থাকে , তবে এইচটিএমএল <base/>উপাদানটি সেই উত্সের URL টি ব্যবহার করে মাথায় চাপ দেওয়া হবে, এইভাবে, এইচটিএমএল ইউআরআইগুলি /some/resource/file.extআইফ্রেমের অভ্যন্তর মূল URL দ্বারা সঠিকভাবে আনা হবে।

function patchIframeHtml(html, origin, params = {}) {
  // Create a DOM parser
  const parser = new DOMParser();

  // Create a document parsing the HTML as "text/html"
  const doc = parser.parseFromString(html, 'text/html');

  // Create the script element that will be injected to the iFrame
  const script = doc.createElement('script');

  // Set the script code
  script.textContent = `
    window.addEventListener('load', () => {
      // Set iFrame document "height: auto" and "overlow-y: auto",
      // so to get auto height. We set "overlow-y: auto" for demontration
      // and in usage it should be "overlow-y: hidden"
      document.body.style.height = 'auto';
      document.body.style.overflowY = 'auto';

      poseResizeMessage();
    });

    window.addEventListener('resize', poseResizeMessage);

    function poseResizeMessage() {
      window.top.postMessage({
        // iframeWidth: document.body.scrollWidth,
        iframeHeight: document.body.scrollHeight,
        // pass the params as encoded URI JSON string
        // and decode them back inside iFrame
        params: JSON.parse(decodeURIComponent('${encodeURIComponent(JSON.stringify(params))}'))
      }, '*');
    }
  `;

  // Append the custom script element to the iFrame body
  doc.body.appendChild(script);

  // If we have an origin URL,
  // create a base tag using that origin
  // and prepend it to the head
  if (origin) {
    const base = doc.createElement('base');
    base.setAttribute('href', origin);

    doc.head.prepend(base);
  }

  // Return the document altered HTML that contains the injected script
  return doc.documentElement.outerHTML;
}

getIframeHtml:

যদি একটি প্রক্সি ব্যবহার করে সিওআরএসকে বাইপাস করে কোনও পৃষ্ঠার এইচটিএমএল পাওয়ার জন্য একটি ক্রিয়া useProxy প্যারাম সেট করা । postMessageআকারের ডেটা প্রেরণ করার সময় অতিরিক্ত প্যারামিটারগুলি পাস করা হবে ।

function getIframeHtml(url, useProxy = false, params = {}) {
  return new Promise(resolve => {
    const xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
      if (xhr.readyState == XMLHttpRequest.DONE) {
        // If we use a proxy,
        // set the origin so it will be placed on a base tag inside iFrame head
        let origin = useProxy && (new URL(url)).origin;

        const patchedHtml = patchIframeHtml(xhr.responseText, origin, params);
        resolve(patchedHtml);
      }
    }

    // Use cors-anywhere proxy if useProxy is set
    xhr.open('GET', useProxy ? `https://cors-anywhere.herokuapp.com/${url}` : url, true);
    xhr.send();
  });
}

বার্তা ইভেন্টের হ্যান্ডলার ফাংশনটি "একই উত্স iFrame আকার" এর মতোই ।

আমরা এখন আমাদের কাস্টম জেএস কোড ইনজেকশন সহ কোনও আইফ্রেমের অভ্যন্তরে ক্রস অরিজিন ডোমেন লোড করতে পারি:

<!-- It's important that the iFrame must have a 100% width 
     for the resize event to work -->
<iframe id="iframe-cross" style="width: 100%"></iframe>

<script>
window.addEventListener('DOMContentLoaded', async () => {
  const crossDomainHtml = await getIframeHtml(
    'https://en.wikipedia.org/wiki/HTML', true /* useProxy */, { id: 'iframe-cross' }
  );

  // We use srcdoc attribute to set the iFrame HTML instead of a src URL
  document.getElementById('iframe-cross').setAttribute('srcdoc', crossDomainHtml);
});
</script>

এবং আমরা overflow-y: autoআইফ্রেম বডি ব্যবহার করে এমনকি কোনও উল্লম্ব স্ক্রোলিং ছাড়াই এর সামগ্রীর পুরো উচ্চতায় আইফ্রেম আকারে পেয়ে যাব ( করতে হবে এটি এমন হওয়া উচিত overflow-y: hiddenযাতে আমরা আকার পরিবর্তনে স্ক্রোলবার ঝাঁকুনি না পাই )।

আপনি এটি অনলাইনে চেক করতে পারেন এখানে

আবার খেয়াল করে দেখুন যে এটি একটি হ্যাক এবং এটি এড়ানো উচিত ; আমরা ক্রস-অরিজিন আইফ্রেম নথিটি অ্যাক্সেস করতে পারি না বা কোনও ধরণের জিনিস ইনজেকশন করতে পারি না


1
ধন্যবাদ! দুর্দান্ত উত্তর।
ফেরিট করুন

1
ধন্যবাদ. দুর্ভাগ্যক্রমে cors-anywhereএই মুহুর্তে ডাউন তাই আপনি ডেমো পৃষ্ঠাটি দেখতে পাচ্ছেন না । আমি কপিরাইটের কারণে বাহ্যিক সাইটের স্ক্রিনশট যুক্ত করতে চাই না। যদি এটি দীর্ঘকাল ধরে থাকে তবে আমি অন্য একটি সিওআরএস প্রক্সি যুক্ত করব।
ক্রিস্টোস লাইট্রাস

2

প্রধানত সিএসএস আপনাকে এমন কিছু করতে সক্ষম করে যা আপনাকে কন্টেন্টের আকারকে কীভাবে পরিমাপ করতে পারে তা ভঙ্গ করতে পারে তার কারণেই এগুলি একটি আইফ্রেমে সামগ্রীর আকার নিয়ে কাজ করার ক্ষেত্রে প্রচুর জটিলতা রয়েছে।

আমি একটি লাইব্রেরি লিখেছি যা এই সমস্ত বিষয়ের যত্ন নেয় এবং ক্রস ডোমেনও কাজ করে, আপনি এটি সহায়ক হতে পারেন find

https://github.com/davidjbradshaw/iframe-resizer


1
শান্ত! যে পরীক্ষা করতে হবে!
ফেরিট করুন

0

আমার সমাধানটি গিটহাব এবং জেএসফিডেলে রয়েছে

অনুপাত অনুপাত অনুমান ব্যতীত প্রতিক্রিয়াশীল iframe জন্য একটি সমাধান উপস্থাপন।

উইন্ডোটি পুনরায় আকার দেওয়ার সময় অন্য কথায়, প্রয়োজনে iframe এর আকার পরিবর্তন করা The এটি নতুন উইন্ডো আকার পেতে এবং ফলস্বরূপ iframe আকার পরিবর্তন করতে জাভাস্ক্রিপ্ট সঙ্গে সঞ্চালিত হয়।

এনবি: পৃষ্ঠাটি লোড হওয়ার পরে পুনরায় আকার ফাংশনটি কল করতে ভুলবেন না যেহেতু পৃষ্ঠা লোড হওয়ার পরে উইন্ডোটি নিজেই পুনরায় আকার না দেয়।

কোড

index.html

<!DOCTYPE html>
<!-- Onyr for StackOverflow -->

<html>

<head> 
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <title>Responsive Iframe</title>
    <link rel="stylesheet" type="text/css" href="./style.css">
</head>

<body id="page_body">
    <h1>Responsive iframe</h1>

    <div id="video_wrapper">
        <iframe id="iframe" src="https://fr.wikipedia.org/wiki/Main_Page"></iframe>
    </div>

    <p> 
        Presenting a solution for responsive iframe without aspect
        ratio assumption.<br><br>
    </p>

    <script src="./main.js"></script>
</body>

</html>

style.css

html {
    height: 100%;
    max-height: 1000px;
}

body {
    background-color: #44474a;
    color: white;
    margin: 0;
    padding: 0;
}

#videoWrapper {
    position: relative;
    padding-top: 25px;
    padding-bottom: 100px;
    height: 0;
    margin: 10;
}
#iframe {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

main.js

let videoWrapper = document.getElementById("video_wrapper");

let w;
let h;
let bodyWidth;
let bodyHeight;

// get window size and resize the iframe
function resizeIframeWrapper() {
    w = window.innerWidth;
    h = window.innerHeight;

    videoWrapper.style["width"] = `${w}px`;
    videoWrapper.style["height"] = `${h - 200}px`;
}

// call the resize function when windows is resized and after load
window.onload = resizeIframeWrapper;
window.onresize = resizeIframeWrapper;

আমি এই জন্য কিছু সময় ব্যয়। আমি আশা করি আপনি এটি উপভোগ করবেন =)

সম্পাদনা এটি সম্ভবত সেরা জেনেরিক সমাধান। যাইহোক, খুব ছোট তৈরি করা হলে, iframe সঠিক আকার দেওয়া হয় না। এটি আপনি যদি ব্যবহার করছেন তবে এটি নির্দিষ্ট। যদি আপনার আইফ্রেমে কোড না থাকে তবে এই ঘটনার উপযুক্ত উত্তর দেওয়া সম্ভব নয়, কারণ আপনার কোডে কোনও আকার নেই তা জানার উপায় নেই যে কোনও আকারটি যদি ইফ্র্রেমে যথাযথভাবে প্রদর্শিত হতে পারে তার চেয়ে বেশি পছন্দ হয়।

@ ক্রিসটোস লাইট্রা দ্বারা উপস্থাপিত একটি মাত্র কিছু হ্যাক কৌশলটি তৈরি করতে পারে তবে এটি প্রতি আইফ্রেমের জন্য কখনই কাজ করবে না। শুধু একটি বিশেষ পরিস্থিতিতে।


চেষ্টা করার জন্য ধন্যবাদ! তবে এটি প্রত্যাশার মতো কাজ করছে না। আইফ্রেমের সামগ্রী যখন ছোট হয় তখনও ধারকটির অতিরিক্ত জায়গা থাকে। এটি দেখুন: jsfiddle.net/6p2suv07/3 আমি iframe এর src পরিবর্তন করেছি।
ফেরিট করুন

আমি "অতিরিক্ত স্থান" দিয়ে আপনার সমস্যাটি বোঝার বিষয়ে নিশ্চিত নই। উইন্ডোটির সর্বনিম্ন আকার 100 পিক্স প্রস্থ। Iframe পাত্রে ফিট করে। আপনার iframe ভিতরে লেআউট আমার নিয়ন্ত্রণে নেই। আমি আপনার প্রশ্নের উত্তর। আপনি যদি আরও সহায়তা চান তবে দয়া করে আপনার সম্পাদনা করুন
ওনিয়ার

একটি ছবি রাখুন এবং এটি বর্ণনা করুন
ওনিয়ার

আইফ্রেমে কনটেইনারটি যে সমস্ত স্থান দেয় সেটি গ্রহণ করে, জিনিসটি হ'ল, যখন আইফ্রেমের সামগ্রী ছোট হয়, তখন এটি গ্রহণ করতে পারে এমন সমস্ত স্থানের প্রয়োজন হয় না। সুতরাং, ধারকটি কেবল iframe এ পর্যাপ্ত জায়গা দিতে হবে, আর কম নয়।
ফেরিট করুন

Iframe এর উচ্চতার জন্য, এটি কারণ আমার উদাহরণে উইন্ডো দ্বারা স্থানের উচ্চতা সীমাবদ্ধ। এটাই? আপনার উদাহরণটি যদি আপনি ব্যবহার করেন তবে আপনার কাছে নির্দিষ্ট, আমি একটি সাধারণ উত্তর দিয়েছি যা গ্রহণ করা উচিত। অবশ্যই কোডটি
টুইঙ্ক করা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.