Kırık resimleri değiştirmek için jQuery / JavaScript


546

Bir sürü resim içeren bir web sayfam var. Bazen görüntü kullanılamayabilir, bu nedenle istemcinin tarayıcısında bozuk bir görüntü gösterilir.

Görüntü kümesini almak, kırık görüntülere filtre uygulamak ve src'yi değiştirmek için jQuery'i nasıl kullanabilirim?


- Bunu jQuery ile yapmanın daha kolay olacağını düşündüm, ancak sadece saf bir JavaScript çözümü, yani Prestaul tarafından sağlanan çözümün daha kolay olduğu ortaya çıktı.

Yanıtlar:


760

onErrorGörüntünün kaynağını JavaScript kullanarak yeniden ataması için olayı işleme:

function imgError(image) {
    image.onerror = "";
    image.src = "/images/noimage.gif";
    return true;
}
<img src="image.png" onerror="imgError(this);"/>

Veya bir JavaScript işlevi olmadan:

<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />

Aşağıdaki uyumluluk tablosu, hata özelliğini destekleyen tarayıcıları listeler:

http://www.quirksmode.org/dom/events/error.html


132
Muhtemelen src'yi ayarlamadan önce hataları temizlemek istersiniz . Aksi takdirde noimage.gif de yoksa "yığın taşması" ile sonuçlanabilir.
pcorcoran

45
Javascript etkinlikleri için satır içi özelliklerden uzaklaştığımızı umuyordum ve umuyoruz ...
redsquare

24
redsquare ... onları kontrol altında tutmaya karar verirseniz mükemmel bir şekilde anlaşılabilir ve işaretlemenizin gerçekte ne olacağını yansıtmasını istediğinizde bile yararlı olabilir.
Nicole

2
İyi nokta NickC, neler olduğunu gösteren işaretleme hakkında, baktığımda sadece kısıldım: P
SSH Bu

38
@ redsquare, tamamen katılıyorum, ama bu eşsiz bir durum. Satır içi, dinleyiciyi, dinleyiciniz eklenmeden önce tetiklemeyeceği mutlak bir kesinlik ile ekleyebileceğiniz tek yerdir. Belgenin sonunda yaparsanız veya DOM'un yüklenmesini beklerseniz bazı görüntülerde hata olayını kaçırabilirsiniz. Olay tetiklendikten sonra bir hata işleyici eklemeniz iyi olmaz.
Prestaul

201

Ben inşa kullanmak errorişleyicisi:

$("img").error(function () {
    $(this).unbind("error").attr("src", "broken.gif");
});

Düzenleme:error() yöntem önerilmiyor jquery 1.8 ve üzeri. Bunun yerine şunu kullanmalısınız .on("error"):

$("img").on("error", function () {
    $(this).attr("src", "broken.gif");
});

112
Bu tekniği kullanırsanız, olayın bağlantısını kesmenize gerek kalmaması için "one" yöntemini kullanabilirsiniz: $ ('img'). One ('hata', işlev () {this.src = 'broken.gif';}) ;
Prestaul

7
+1 Ama onu ayırmak zorunda mısın? Bağlamıyorsanız dinamik görüntülerde (örneğin üzerine gelindiğinde değişebilen) güzel çalışır.
Aximili

15
Bence onu ayırmazsanız ve broken.gif src başvurusu herhangi bir nedenle yüklenemezse, tarayıcıda kötü şeyler olabilir.
travis

4
@travis, bu çağrıyı hangi noktada yaparsınız? Bu yöntemi kullanmanın ve hata olayı tetiklenmeden önce işleyicinizin iliştirildiğinden emin olmanın herhangi bir yolu var mı?
Prestaul

5
Olay işleyicisi eklenmeden önce hatanın tetiklendiği bir durum örneği: jsfiddle.net/zmpGz/1 Bu işleyiciyi eklemenin başarısız güvenli bir yolu olup olmadığını gerçekten merak ediyorum ...
Prestaul

120

Benim gibi biri, erroretkinliği dinamik bir HTML imgetiketine eklemeye çalışırsa, şunu belirtmek isterim, bir yakalama var:

Görünüşe imghata olayları kabarcık yok aksine çoğu tarayıcılarda standart diyor.

Yani, aşağıdaki gibi bir şey işe yaramaz :

$(document).on('error', 'img', function () { ... })

Umarım bu başka birine yardımcı olur. Keşke burada bu iş parçacığında görmüştü. Ama etmedim. Bu yüzden ekliyorum


işe yaramadı. Ölü bir görüntüyü dinamik olarak yüklüyorum ve dom'a ekliyorum ve 'hata' olayı tetiklenmiyor.
vsync

59

İşte bağımsız bir çözüm:

$(window).load(function() {
  $('img').each(function() {
    if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});

5
Neredeyse doğru ... IE'de doğru bir görüntü yine de dönecektir (typeof (this.naturalWidth) == "undefined") == true; - if ifadesini (! This.complete || (! $. Browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0))) olarak değiştirdim
Şubat'ta Sugendran

3
bu kural, sayfa yüklendikten sonra bozuk bir görüntüyü algılayabildiği için bu kuraldır. Buna ihtiyacım vardı.
northamerican

@Sugendran $.browserartık kullanımdan kaldırıldı ve kaldırıldı, bunun yerine özellik algılamayı kullanın (bu durumda daha karmaşık hale gelir).
lee penkman

3
Bağımsız ama jQuery gerektirir?
Charlie

Bu harika çalışıyor, ancak görüntünün src değeri döndürüldüğünde 204 No Contentkırık bir görüntü olacaktır.
Carson Reinke

35

Sonra ne olduğunu inanıyorum: jQuery.Preload

Demodan örnek kod, yükleme ve bulunamadı görüntüleri belirtirsiniz ve hazırsınız:

$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});

1
jQuery.Preload, örnek kodu kullanmak için gereken bir eklentidir.
Dan Lord

17
Evet ... bu ilk satırdaki cevaba bağlanıyor.
Nick Craver

Teşekkür ederim Nick, bu Firefox'un 8+ yıllık sorunu için kırık görüntüler yerine resim değiştirme göstermemesi için iyi bir çözüm gibi görünüyor. Ayrıca küçük şeyi markalayabilirsiniz ... tekrar teşekkürler.
klewis


19

OP SRC'nin yerini ararken, eminim ki bu soruya çarpan birçok kişi sadece kırık görüntüyü gizlemek isteyebilir, bu durumda bu basit çözüm benim için harika çalıştı.

Satır İçi JavaScript Kullanma:

<img src="img.jpg" onerror="this.style.display='none';" />

Harici JavaScript Kullanma:

var images = document.querySelectorAll('img');

for (var i = 0; i < images.length; i++) {
  images[i].onerror = function() {
    this.style.display='none';
  }
}
<img src='img.jpg' />

Modern Harici JavaScript Kullanma:

document.querySelectorAll('img').forEach((img) => {
  img.onerror = function() {
    this.style.display = 'none';
  }
});
<img src='img.jpg' />

NoteList.forEach ve ok işlevleri için tarayıcı desteğine bakın .


1
Bunu benim için çok benzer bir soruna en güvenilir çözüm olarak buldum. Kırık bir görüntü alternatifi göstermek yerine herhangi bir görüntü göstermemeyi tercih ederim. Teşekkürler.
pc_

Bu, İçerik Güvenliği İlkesi'nin satır içi komut dosyalarına izin vermemesi durumunda açık değildir.
isherwood

@isherwood İyi bir nokta. Harici bir JS dosyası üzerinden çalışan bir çözüm ekledim.
Nathan Arthur

11

İşte tüm kırık görüntüleri değiştirmek için hızlı ve kirli bir yol ve HTML kodunu değiştirmenize gerek yok;)

kod örneği

    $("img").each(function(){
        var img = $(this);
        var image = new Image();
        image.src = $(img).attr("src");
        var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
        if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
            $(img).unbind("error").attr("src", no_image).css({
                height: $(img).css("height"),
                width: $(img).css("width"),
            });
        }
  });

9

Gereksinimlerimi karşılayacak bir komut dosyası bulamadım, bu yüzden bozuk görüntüleri kontrol etmek ve düzeltilinceye kadar her dört saniyede bir yeniden yüklemeyi denemek için yinelemeli bir işlev yaptım.

Sanki tarafından yüklenmemiş gibi 10 denemeyle sınırlandırdım, o zaman görüntü sunucuda olmayabilir ve işlev sonsuz bir döngüye girerdi. Yine de test ediyorum. Ayarlamaktan çekinmeyin :)

var retries = 0;
$.imgReload = function() {
    var loaded = 1;

    $("img").each(function() {
        if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {

            var src = $(this).attr("src");
            var date = new Date();
            $(this).attr("src", src + "?v=" + date.getTime()); //slightly change url to prevent loading from cache
            loaded =0;
        }
    });

    retries +=1;
    if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
                        // are not present on server, the recursion will break the loop
        if (loaded == 0) {
            setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
        }
        // All images have been loaded
        else {
            // alert("images loaded");
        }
    }
    // If error images cannot be loaded  after 10 retries
    else {
        // alert("recursion exceeded");
    }
}

jQuery(document).ready(function() {
    setTimeout('$.imgReload()',5000);
});

Görüntüleri yeniden yüklemeye çalışırken iyi fikir. Bu yüklenen / otomatik oluşturulan görüntüler için kullanışlıdır ve sayfa yüklenirken sunucu kazanılmamış / tamamlanmamış olabilir. Bu orijinal biçimlendirme. Biraz fazla tutarsız ve benim zevkime göre değil ...
Joakim

8

Bu berbat bir tekniktir, ancak neredeyse garantilidir:

<img ...  onerror="this.parentNode.removeChild(this);">

6

Bunun için GitHub'ın kendi getirmesini kullanabilirsiniz:

Ön uç : https://github.com/github/fetch
veya bir Node.js sürümü olan Backend için: https://github.com/bitinn/node-fetch

fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }

Düzenleme: Bu yöntem XHR'nin yerini alacak ve sözde Chrome'da zaten var. Gelecekte bunu okuyan herkes için, yukarıda belirtilen kütüphaneye ihtiyacınız olmayabilir.


6

Bu JavaScript, çapraz tarayıcı uyumlu olmalı ve çirkin işaretleme olmadan sunar onerror="":

var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
    validateImage = function( domImg ) {
        oImg = new Image();
        oImg.onerror = function() {
            domImg.src = sPathToDefaultImg;
        };
        oImg.src = domImg.src;
    },
    aImg = document.getElementsByTagName( 'IMG' ),
    i = aImg.length;

while ( i-- ) {
    validateImage( aImg[i] );
}

CODEPEN:


için upvotewhile (i--)
S3C

4

Kullanarak daha iyi çağrı

jQuery(window).load(function(){
    $.imgReload();
});

Kullanmak document.readygerekli olmadığından, görüntülerin yüklendiği anlamına gelir, sadece HTML. Bu nedenle, gecikmeli bir aramaya gerek yoktur.


4

CoffeeScript varyantı:

Görüntü gerçekten orada olsa bile Turbolinks ile .error () yönteminin Firefox'ta bazen yükselmesine neden olan bir sorunu düzeltmek için yaptım.

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)

4

Prestaul'un cevabını kullanarak bazı kontroller ekledim ve jQuery yolunu kullanmayı tercih ediyorum.

<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>

function imgError(image, type) {
    if (typeof jQuery !== 'undefined') {
       var imgWidth=$(image).attr("width");
       var imgHeight=$(image).attr("height");

        // Type 1 puts a placeholder image
        // Type 2 hides img tag
        if (type == 1) {
            if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
                $(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
            } else {
               $(image).attr("src", "http://lorempixel.com/200/200/");
            }
        } else if (type == 2) {
            $(image).hide();
        }
    }
    return true;
}

4

Eğer imgile innerHTML, örneğin: $("div").innerHTML = <img src="wrong-uri">eklediyseniz, başarısız olursa başka bir görüntü yükleyebilirsiniz, örneğin, bu:

<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>

<img src="wrong-uri" onerror="javascript:imgError(this)">

Neden javascript: _ihtiyaç duyulur? Komut dosyası etiketleri aracılığıyla DOM'a enjekte edilen komut dosyaları, enjekte innerHTMLedildikleri sırada çalışmadığından, açık olmanız gerekir.


4

Bu yazıyı diğer SO yazısına bakarken buldum . Aşağıda verdiğim cevabın bir kopyası.

Bunun eski bir iş parçacığı olduğunu biliyorum, ama React popüler oldu ve belki de React kullanan biri buraya aynı soruna bir cevap aramaya gelecek.

Eğer Tepki kullanıyorsanız Yani, takımı tepki şehrinden Ben Alpert tarafından sağlanan bir cevap orijinal idi aşağıda gibi bir şey, yapabileceği burada

getInitialState: function(event) {
    return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
    this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
    return (
        <img onError={this.handleError} src={src} />;
    );
}

4

"Onerror" olayını kullanarak kırık görüntüyü değiştirmek için bir keman yarattım . Bu size yardımcı olabilir.

    //the placeholder image url
    var defaultUrl = "url('https://sadasd/image02.png')";

    $('div').each(function(index, item) {
      var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '$1');
      $('<img>', {
        src: currentUrl
      }).on("error", function(e) {
        $this = $(this);
        $this.css({
          "background-image": defaultUrl
        })
        e.target.remove()
      }.bind(this))
    })

4

İşte JQuery tarafından sarılmış HTML5 Image nesnesini kullanan bir örnek. Birincil resim URL'si için yükleme işlevini çağırın ve bu yükleme bir hataya neden oluyorsa, resmin src özelliğini yedek bir URL ile değiştirin.

function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
    var $img = $('#' + imgId);
    $(new Image()).load().error(function() {
        $img.attr('src', backupUrl);
    }).attr('src', primaryUrl)
}

<img id="myImage" src="primary-image-url"/>
<script>
    loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>

4

Saf JS. Benim görevim: 'bl-once.png' resmi boşsa -> dizi listesinden (şu anki dizinde) ilk resmi (404 durumu olmayan) ekle:

<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">

Belki iyileştirilmesi gerekiyor, ancak:

var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array
    var path;
    var imgNotFounded = true; // to mark when success

    var replaceEmptyImage = {
        insertImg: function (elem) {

            if (srcToInsertArr.length == 0) { // if there are no more src to try return
                return "no-image.png";
            }
            if(!/undefined/.test(elem.src)) { // remember path
                path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"
            }
            var url = path + "/" + srcToInsertArr[0];

            srcToInsertArr.splice(0, 1); // tried 1 src

            
                if(imgNotFounded){ // while not success
                    replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE
                }
            

        },
        getImg: function (src, path, elem) { // GET IMAGE

            if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"
                
                var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]
                var name = pathArr[pathArr.length - 1]; // "needed.png"

                xhr = new XMLHttpRequest();
                xhr.open('GET', src, true);
                xhr.send();

                xhr.onreadystatechange = function () {

                    if (xhr.status == 200) {
                        elem.src = src; // insert correct src
                        imgNotFounded = false; // mark success
                    }
                    else {
                        console.log(name + " doesn't exist!");
                        elem.onerror();
                    }

                }
            }
        }

    };

Bu nedenle, src'ime doğru 'needed.png' veya geçerli dir'den 'no-image.png' ekleyecektir.


Aynı sitede kullandım. Bu sadece bir fikir. Gerçek kodum geliştirildi ...
Дмитрий Дорогонов

3

Daha iyi bir yol olup olmadığından emin değilim, ancak bunu elde etmek için bir hack düşünebilirim - img URL'sine Ajax gönderebilir ve görüntünün gerçekten geri gelip gelmediğini görmek için yanıtı ayrıştırabilirsiniz. Eğer 404 ya da benzeri bir şey olarak geri geldiyse, img'yi değiştirin. Gerçi bunun oldukça yavaş olmasını bekliyorum.


3

Sorunumu şu iki basit işlevle çözdüm:

function imgExists(imgPath) {
    var http = jQuery.ajax({
                   type:"HEAD",
                   url: imgPath,
                   async: false
               });
    return http.status != 404;
}

function handleImageError() {
    var imgPath;

    $('img').each(function() {
        imgPath = $(this).attr('src');
        if (!imgExists(imgPath)) {
            $(this).attr('src', 'images/noimage.jpg');
        }
    });
}

3

jQuery 1.8

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .error(function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

jQuery 3

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .on("error", function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

referans


3

Ben olay heyet ve olay üzerinde yakalama ile daha şık bir yol olduğunu düşünüyorum window's erroryedek resim yüküne başarısız bile.

img {
  width: 100px;
  height: 100px;
}
<script>
  window.addEventListener('error', windowErrorCb, {
    capture: true
  }, true)

  function windowErrorCb(event) {
    let target = event.target
    let isImg = target.tagName.toLowerCase() === 'img'
    if (isImg) {
      imgErrorCb()
      return
    }

    function imgErrorCb() {
      let isImgErrorHandled = target.hasAttribute('data-src-error')
      if (!isImgErrorHandled) {
        target.setAttribute('data-src-error', 'handled')
        target.src = 'backup.png'
      } else {
        //anything you want to do
        console.log(target.alt, 'both origin and backup image fail to load!');
      }
    }
  }
</script>
<img id="img" src="error1.png" alt="error1">
<img id="img" src="error2.png" alt="error2">
<img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">

Önemli olan :

  1. Kodu koyun ve headilk satır içi komut dosyası olarak yürütülür. Yani, komut dosyasından sonra meydana gelen hataları dinleyecektir.

  2. Hataları yakalamak için, özellikle kabarmayan olaylarda olay yakalamayı kullanın.

  3. Her görüntüde bağlayıcı olayları engelleyen olay yetkisi kullanın.

  4. Hata imgelemanına aşağıdaki gibi sonsuz döngüsünün backup.pngkaybolmasını önlemek için bir öznitelik verin.backup.png

img hatası-> backup.png-> hata-> backup.png-> hata -> ,,,,,


Bu açık ara en iyi anwer. Önerebileceğim tek şey let isImgErrorHandled = target.src === 'backup.png';biraz basitleştirdiği için kullanmaktır .
Sabo

@ Sabun, küçük bir sorun var çünkü src yolu atadığım yola eşit olmayabilir. Örneğin target.src='backup.png', ama bir dahaki sefere console.log(target.src)olmayabilirbackup.png
xianshenglu

2
;(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
    return this.one('error', function () {
        var self = this;
        this.src = (fallback || 'http://lorempixel.com/$width/$height')
        .replace(/\$(\w+)/g, function (m, t) { return self[t] || ''; });
    });
};

Bir yer tutucu yol geçirebilir ve başarısız olan görüntü nesnesindeki tüm özelliklere şu yolla erişebilirsiniz $*:

$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');

http://jsfiddle.net/ARTsinn/Cu4Zn/


2

Bu beni yıllardır sinirlendiriyor. CSS düzeltmem, öğesinde bir arka plan görüntüsü ayarlar img. Dinamik bir görüntü srcön plana yüklenmediğinde, bir yer tutucu img's bg' sinde görünür . Bu, resimlerinizin varsayılan boyutu varsa (örn height. min-height, widthVe / veya min-width) çalışır.

Kırık görüntü simgesini göreceksiniz, ancak bu bir gelişme. IE9'a başarıyla test edildi. iOS Safari ve Chrome kırık bir simge bile göstermiyor.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}

srcBir arka plan titremesi olmadan yüklemeye zaman vermek için küçük bir animasyon ekleyin . Chrome arka planda sorunsuz bir şekilde kaybolur, ancak masaüstü Safari bunu yapmaz.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
  -webkit-animation: fadein 1s;
  animation: fadein 1s;                     
}

@-webkit-keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

2

Resim yüklenemiyorsa (örneğin, sağlanan URL'de bulunmadığından) resim URL'si varsayılan olarak değiştirilir,

.Error () hakkında daha fazla bilgi için

$('img').on('error', function (e) {
  $(this).attr('src', 'broken.png');
});


1

Ben de aynı problemi yaşadım. Bu kod benim durumumda iyi çalışıyor.

// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});

1

Bazen erroretkinliği kullanmak mümkün değildir, örneğin, konsolu, yer işaretini veya eşzamansız olarak yüklenen bir komut dosyasını çalıştırdığınızda olduğu gibi zaten yüklenmiş bir sayfada bir şey yapmaya çalıştığınız için. Bu durumda, img.naturalWidthve img.naturalHeight0'ı kontrol etmek hile yapıyor gibi görünüyor.

Örneğin, tüm kırık görüntüleri konsoldan yeniden yüklemek için bir snippet:

$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}

0

Bunu en iyi şekilde buldum, herhangi bir görüntü ilk kez yüklenemezse, DOM'dan tamamen kaldırılır. console.clear()404 hataları try / catch bloklarıyla atlanamayacağından, yürütme konsol penceresini temiz tutar.

$('img').one('error', function(err) {
    // console.log(JSON.stringify(err, null, 4))
    $(this).remove()
    console.clear()
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.