Jak dodać zdarzenie onload do elementu div

231

Jak dodać onloadzdarzenie do elementu?

Mogę uzyć:

<div onload="oQuickReply.swap();" ></div>

dla tego?

monkey_boys
źródło
najlepiej bodylepiejdiv
KingRider
2
divelementy nie „ładują się”.
AMN
1
Jest teraz bardziej odpowiednia odpowiedź - być może możesz zmienić akceptację?
mplungjan

Odpowiedzi:

233

Nie możesz. Najłatwiejszym sposobem, aby to zadziałało, byłoby umieszczenie wywołania funkcji bezpośrednio za elementem

Przykład:

...
<div id="somid">Some content</div>
<script type="text/javascript">
   oQuickReply.swap('somid');
</script>
...

lub - jeszcze lepiej - tuż przed </body>:

...
<script type="text/javascript">
   oQuickReply.swap('somid');
</script>
</body>

... więc nie blokuje ładowania następującej treści.

DanMan
źródło
3
W zależności od zastosowania nie jest lepiej postawić go przed </body>. np. jeśli chcesz ukryć <div>tylko jeśli JavaScript jest włączony, ale unikaj „flashowania”. Czas widoczności zależy od tego, jak długo przeglądarka musi załadować / parsować wszystkie wbudowane / zewnętrzne skrypty.
mgutt
Czy to jest anty-wzorzec, ponieważ lepiej jest trzymać wszystkie pliki js w swoim własnym pliku? Czy istnieje sposób selektywnego uruchamiania js, gdy pewne elementy są ładowane do dokumentu?
Ryan Walton,
1
To nie jest anty-wzorzec, ale zwykle czekasz na załadowanie DOM, a następnie wykonujesz wszystkie czynności JS.
DanMan
1
Rzuć ten link tutaj dla każdego, kto spotka się z tą odpowiedzią w3schools.com/tags/ev_onload.asp - Wszystkie obsługiwane obecnie elementy HTMLonload
Brandon Benefield
Ta odpowiedź nie jest już aktualna. Oto nowy
mplungjan,
74

onloadZdarzenie może być używany tylko na document(body)sobie, ram, obrazów i skryptów. Innymi słowy, może być dołączony tylko do ciała i / lub każdego zewnętrznego zasobu . Div nie jest zasobem zewnętrznym i jest ładowany jako część ciała, więc onloadzdarzenie nie ma tam zastosowania.

kijin
źródło
18
Można go używać nie tylko w elemencie body, np. W obrazie i ramce iframe. w3schools.com/jsref/event_onload.asp
Joe
2
Warto zauważyć, że skrypty wbudowane NIE są zasobami zewnętrznymi, a zatem onloadnie działają na żadnym <script>bez srcatrybutu HTML (próbowałem skorzystać z tej porady w skrypcie wbudowanym i okazało się, że nie działa)
gog
64

Możesz uruchomić niektóre js automatycznie na elemencie IMG, używając onerror i bez src.

<img src onerror='alert()'>
John Williams
źródło
4
Znakomity! Można go również użyć do wyzwolenia maszynopisu z kątownika: img src (error) = "function ()" />
Brian Richardson
1
To fantastyczne podejście. Proszę zobaczyć moje rozwinięcie twojego rozwiązania tutaj: stackoverflow.com/questions/4057236/…
Rounin
Caniuse? ͏͏͏͏͏͏͏
Pacerier
28

Zdarzenie onload obsługuje tylko kilka tagów, takich jak wymienione poniżej.

<body>, <frame>, <iframe>, <img>, <input type="image">, <link>, <script>, <style>

Tutaj odniesienie do zdarzenia onload

Samda
źródło
17

Spróbuj tego! I nigdy nie używaj spustu dwa razy na div!

Możesz zdefiniować funkcję do wywołania przed znacznikiem div.

$(function(){
    $('div[onload]').trigger('onload');
});

DEMO: jsfiddle

Kuofp
źródło
Powyżej jsfiddle nie ma modułu ładującego jQuery - i nie działa.
Arif Burhan,
@Arif Burhan, nie rozumiem. Ładuję JQuery (edge). Czy mógłbyś sprawdzić jeszcze raz? Widzę „Hello World” nawet za pomocą telefonu komórkowego.
Kuofp,
@ Kuofp To skrzypce tak naprawdę nie ma wywołań modułów obsługi po załadowaniu ich elementów docelowych. Po prostu używa jquery do wyszukiwania elementów, które mają atrybut (w twoim przypadku onload), a następnie wywołuje te funkcje. Skrypt działa, nawet jeśli zmienisz atrybut na coś innego niż onloadnp. Jsfiddle.net/mrszgbxh
Trindaz 16.08.16
1
@Trindaz Dokładnie! Innymi słowy, skrypty działają jak zdarzenie onload. Dzięki za komentarz!
Kuofp,
10

Chcę tylko dodać tutaj, że jeśli ktoś chce wywołać funkcję podczas zdarzenia div div i nie chcesz używać jQuery (z powodu konfliktu, jak w moim przypadku), po prostu wywołaj funkcję po całym kodzie HTML lub dowolnym inny kod, który napisałeś, w tym kod funkcji i po prostu wywołaj funkcję.

/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
   function_name();
</script>

LUB

/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
 function my_func(){
   function definition;      

  }

 my_func();
</script>
dev_khan
źródło
Czy możesz w ten sposób dodać więcej niż jedną funkcję? tzn. na końcu dokumentu HTML tuż przed znacznikiem </body>? Jeśli tak, to czy kolejność, w jakiej są zapisane, ma znaczenie?
Neo,
Tak, możesz dodać więcej niż jedną funkcję, a kolejność nie będzie miała znaczenia, to zwykły javascript (waniliowy).
dev_khan
7

możemy użyć MutationObserver do skutecznego rozwiązania problemu, dodając poniższy przykładowy kod

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style>
        #second{
            position: absolute;
            width: 100px;
            height: 100px;
            background-color: #a1a1a1;
        }
    </style>
</head>
<body>
<div id="first"></div>
<script>
    var callthis = function(element){
           element.setAttribute("tabIndex",0);
        element.focus();
        element.onkeydown = handler;
        function handler(){
                alert("called")
        }
    }


    var observer = new WebKitMutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            for (var i = 0; i < mutation.addedNodes.length; i++)
            if(mutation.addedNodes[i].id === "second"){
                callthis(mutation.addedNodes[i]);
            }

        })
    });
    observer.observe(document.getElementById("first"), { childList: true });


    var ele = document.createElement('div');
    ele.id = "second"

    document.getElementById("first").appendChild(ele);

</script>

</body>
</html>
użytkownik2364729
źródło
1
Ostatnim razem sprawdziłem zdarzenia mutacji wykonane okropnie.
DanMan
7

W listopadzie 2019 r. Szukam sposobu na stworzenie (hipotetycznego), onparse EventListenerdo <elements>czego się nie zgadzam onload.

(Hipotetyczny) onparse EventListenermusi być w stanie nasłuchiwać podczas analizowania elementu .


Trzecia próba (i ostateczne rozwiązanie)

Byłem bardzo zadowolony z drugiej próby poniżej, ale uderzyło mnie, że mogę skrócić i uprościć kod, tworząc wydarzenie dostosowane do potrzeb:

let parseEvent = new Event('parse');

To najlepsze jak dotąd rozwiązanie.

Przykład poniżej:

  1. Tworzy na zamówienie parse Event
  2. Deklaruje funkcję (którą można uruchomić w window.onloaddowolnym momencie), która:
    • Znajduje dowolne elementy w dokumencie, które zawierają atrybut data-onparse
    • Dołącza parse EventListenerdo każdego z tych elementów
    • Wysyła parse Eventdo każdego z tych elementów, aby wykonaćCallback

Przykład roboczy:

// Create (homemade) parse event
let parseEvent = new Event('parse');

// Create Initialising Function which can be run at any time
const initialiseParseableElements = () => {

  // Get all the elements which need to respond to an onparse event
  let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
  
  // Attach Event Listeners and Dispatch Events
  elementsWithParseEventListener.forEach((elementWithParseEventListener) => {

    elementWithParseEventListener.addEventListener('parse', updateParseEventTarget, false);
    elementWithParseEventListener.dataset.onparsed = elementWithParseEventListener.dataset.onparse;
    elementWithParseEventListener.removeAttribute('data-onparse');
    elementWithParseEventListener.dispatchEvent(parseEvent);
  });
}

// Callback function for the Parse Event Listener
const updateParseEventTarget = (e) => {
  
  switch (e.target.dataset.onparsed) {

    case ('update-1') : e.target.textContent = 'My First Updated Heading'; break;
    case ('update-2') : e.target.textContent = 'My Second Updated Heading'; break;
    case ('update-3') : e.target.textContent = 'My Third Updated Heading'; break;
    case ('run-oQuickReply.swap()') : e.target.innerHTML = 'This <code>&lt;div&gt;</code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
  }
}

// Run Initialising Function
initialiseParseableElements();

let dynamicHeading = document.createElement('h3');
dynamicHeading.textContent = 'Heading Text';
dynamicHeading.dataset.onparse = 'update-3';

setTimeout(() => {

  // Add new element to page after time delay
  document.body.appendChild(dynamicHeading);

  // Re-run Initialising Function
  initialiseParseableElements();

}, 3000);
div {
  width: 300px;
  height: 40px;
  padding: 12px;
  border: 1px solid rgb(191, 191, 191);
}

h3 {
position: absolute;
top: 0;
right: 0;
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>


Drugie podejście

Pierwsza próba poniżej (na podstawie @JohnWilliams"genialny Pusty Hack ) stosuje się sztywno <img />i pracował.

Pomyślałem, że powinno być możliwe <img />całkowite usunięcie zakodowanego na stałe i tylko dynamiczne wstawienie go po wykryciu w elemencie, który musiał uruchomić onparsezdarzenie, atrybutu takiego jak:

data-onparse="run-oQuickReply.swap()"

Okazuje się, że to naprawdę działa bardzo dobrze.

Przykład poniżej:

  1. Znajduje dowolne elementy w dokumencie, które zawierają atrybut data-onparse
  2. Dynamicznie generuje <img src />i dołącza go do dokumentu, natychmiast po każdym z tych elementów
  3. Uruchamia się, onerror EventListenergdy silnik renderujący analizuje każdy<img src />
  4. Wykonuje Callback i usuwa dynamicznie generowane <img src />z dokumentu

Przykład roboczy:

// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');

// Dynamically create and position an empty <img> after each of those elements 
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {

  let emptyImage = document.createElement('img');
  emptyImage.src = '';
  elementWithParseEventListener.parentNode.insertBefore(emptyImage, elementWithParseEventListener.nextElementSibling);
});

// Get all the empty images
let parseEventTriggers = document.querySelectorAll('img[src=""]');

// Callback function for the EventListener below
const updateParseEventTarget = (e) => {

  let parseEventTarget = e.target.previousElementSibling;
  
  switch (parseEventTarget.dataset.onparse) {

    case ('update-1') : parseEventTarget.textContent = 'My First Updated Heading'; break;
    case ('update-2') : parseEventTarget.textContent = 'My Second Updated Heading'; break;
    case ('run-oQuickReply.swap()') : parseEventTarget.innerHTML = 'This <code>&lt;div&gt;</code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
  }
  
  // Remove empty image
  e.target.remove();
}

// Add onerror EventListener to all the empty images
parseEventTriggers.forEach((parseEventTrigger) => {
  
  parseEventTrigger.addEventListener('error', updateParseEventTarget, false);
  
});
div {
  width: 300px;
  height: 40px;
  padding: 12px;
  border: 1px solid rgb(191, 191, 191);
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>


Pierwsze podejscie

Mogę bazować na @JohnWilliams<img src>hacku ” (na tej stronie od 2017 r.) - co do tej pory jest najlepszym podejściem, na jakie się natknąłem.

Przykład poniżej:

  1. Uruchamia się onerror EventListenerpodczas analizy silnika renderowania<img src />
  2. Wykonuje Callback i usuwa <img src />z dokumentu

Przykład roboczy:

let myHeadingLoadEventTrigger = document.getElementById('my-heading-load-event-trigger');

const updateHeading = (e) => {

  let myHeading = e.target.previousElementSibling;
  
  if (true) { // <= CONDITION HERE
    
    myHeading.textContent = 'My Updated Heading';
  }
  
  // Modern alternative to document.body.removeChild(e.target);
  e.target.remove();
}

myHeadingLoadEventTrigger.addEventListener('error', updateHeading, false);
<h2>My Heading</h2>
<img id="my-heading-load-event-trigger" src />

Rounin
źródło
@DavidBradshaw - Nigdy w to nie uwierzysz, ale myślę, że naprawdę go złamałem . Zobacz drugą próbę u góry powyższej odpowiedzi.
Rounin
1
@DavidBradshaw - Zdrap to. Wymyśliłem trzecią próbę . To jest ostateczne rozwiązanie.
Rounin
Może skrócić odpowiedź do wersji 3
David Bradshaw
6

użyj iframe i ukryj go iframe działa jak znacznik body

<!DOCTYPE html>
<html>
<body>

<iframe style="display:none" onload="myFunction()" src="http://www.w3schools.com"></iframe>
<p id="demo"></p>

<script>
function myFunction() {
    document.getElementById("demo").innerHTML = "Iframe is loaded.";
}
</script>

</body>
</html>
dota2pro
źródło
6

Musiałem uruchomić kod inicjujący po włożeniu fragmentu HTML (instancji szablonu) i oczywiście nie miałem dostępu do kodu, który manipuluje szablonem i modyfikuje DOM. Ten sam pomysł dotyczy każdej częściowej modyfikacji DOM poprzez wstawienie elementu HTML, zwykle a <div>.

Jakiś czas temu zrobiłem włamanie ze zdarzeniem onload prawie niewidocznego <img>zawartego w <div>, ale odkryłem, że styl o pustym zasięgu również:

<div .... >
<style scoped="scoped" onload="dosomethingto(this.parentElement);" >   </style>
.....
</div>

Aktualizacja (15 lipca 2017 r.) - <style>obciążenie nie jest obsługiwane w ostatniej wersji IE. Edge go obsługuje, ale niektórzy użytkownicy postrzegają to jako inną przeglądarkę i trzymają się IE. <img>Elementem wydaje się lepiej działa we wszystkich przeglądarkach.

<div...>
<img onLoad="dosomthing(this.parentElement);" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
...
</div>

Aby zminimalizować efekt wizualny i zużycie zasobów obrazu, użyj wbudowanego pliku src, który zachowa go mały i przezroczysty.

Jednym komentarzem, który powinienem zrobić na temat używania, jest <script>to, o ile trudniej jest ustalić, który <div>skrypt jest blisko, szczególnie w szablonach, w których nie można mieć identycznego identyfikatora w każdej instancji generowanej przez szablon. Myślałem, że odpowiedzią może być document.currentScript, ale nie jest to powszechnie obsługiwane. <script>Element nie może określić własne położenie DOM niezawodnie; odniesienie do „tego” wskazuje na główne okno i nie jest pomocne.

Uważam, że konieczne jest zadowalanie się użyciem <img>elementu, mimo że jest głupkowaty. Może to być dziura w strukturze DOM / javascript, która mogłaby użyć wtyczki.

Floyd Kosch
źródło
3

Ponieważ onloadzdarzenie jest obsługiwane tylko w kilku elementach, musisz użyć alternatywnej metody.

Możesz do tego użyć MutationObserver :

const trackElement = element => {
  let present = false;
  const checkIfPresent = () => {
    if (document.body.contains(element)) {
      if (!present) {
        console.log('in DOM:', element);
      }
      present = true;
    } else if (present) {
      present = false;
      console.log('Not in DOM');
    }
  };

  const observer = new MutationObserver(checkIfPresent);
  observer.observe(document.body, { childList: true });
  checkIfPresent();

  return observer;
};

const element = document.querySelector('#element');
const add = () => document.body.appendChild(element);
const remove = () => element.remove();

trackElement(element);
<button onclick="add()">Add</button>
<button onclick="remove()">Remove</button>

<div id="element">Element</div>

jo_va
źródło
2

Naprawdę podoba mi się biblioteka YUI3.

<div id="mydiv"> ... </div>

<script>
YUI().use('node-base', function(Y) {
  Y.on("available", someFunction, '#mydiv')
})

Zobacz: http://developer.yahoo.com/yui/3/event/#onavailable

mjhm
źródło
9
To dość duża kropla JS, którą należy zrzucić na stronę w celu związania singla onload.
meagar
1
@meagar - Racja, choć coraz rzadziej zdarza mi się, że robię tylko dwie lub trzy proste czynności JS na stronie. Martwienie się o kompatybilność między przeglądarkami również doprowadza mnie do szału.
mjhm 30.10.10
0

Uczę się javascript i jquery i przechodziłem przez całą odpowiedź, napotkałem ten sam problem podczas wywoływania funkcji javascript do ładowania elementu div. Próbowałem $('<divid>').ready(function(){alert('test'})i to zadziałało dla mnie. Chcę wiedzieć, że jest to dobry sposób na wykonanie wywołania onload na elemencie div w taki sam sposób, jak przy użyciu selektora jquery.

dzięki

subro
źródło
0

Jak już powiedziano, nie można użyć zdarzenia onLoad na DIV, ale przed tagiem body.

ale jeśli masz jeden plik stopki i umieścisz go na wielu stronach. lepiej najpierw sprawdzić, czy żądany plik div znajduje się na tej stronie, aby kod nie był wykonywany na stronach, które nie zawierają tego DIV, aby przyspieszyć ładowanie i zaoszczędzić trochę czasu na aplikację.

więc musisz nadać temu DIV identyfikator i wykonać:

var myElem = document.getElementById('myElementId');
if (myElem !== null){ put your code here}
Mostafa Yousef
źródło
0

Miałem to samo pytanie i próbowałem uzyskać Div, aby załadował skrypt przewijania, używając onload lub load. Problem, który znalazłem, polegał na tym, że zawsze działało, zanim Div mógł się otworzyć, a nie w trakcie lub po nim, więc tak naprawdę nie działało.

Potem wymyśliłem to jako obejście.

<body>

<span onmouseover="window.scrollTo(0, document.body.scrollHeight);" 
onmouseout="window.scrollTo(0, document.body.scrollHeight);">

<div id="">
</div>

<a href="" onclick="window.scrollTo(0, document.body.scrollHeight);">Link to open Div</a>

</span>
</body>

Umieściłem Div wewnątrz Span i dałem Span dwa zdarzenia, najechanie myszką i mouseout. Następnie pod tym divem umieściłem link, aby otworzyć div, i dałem temu linkowi zdarzenie do kliknięcia. Wszystkie zdarzenia są dokładnie takie same, aby przewinąć stronę w dół na dole strony. Teraz, gdy kliknięty zostanie przycisk otwierający Div, strona częściowo przeskoczy w dół, a Div otworzy się nad przyciskiem, powodując, że zdarzenia najechania kursorem myszy i myszy zostaną przesunięte w dół. Wówczas każdy ruch myszy w tym punkcie popchnie skrypt po raz ostatni.

Selektywny
źródło
0

Możesz użyć interwału, aby to sprawdzić, dopóki się nie załaduje: https://codepen.io/pager/pen/MBgGGM

let checkonloadDoSomething = setInterval(() => {
  let onloadDoSomething = document.getElementById("onloadDoSomething");
  if (onloadDoSomething) {
    onloadDoSomething.innerHTML="Loaded"
    clearInterval(checkonloadDoSomething);
  } else {`enter code here`
    console.log("Waiting for onloadDoSomething to load");
  }
}, 100);
Robert Page
źródło
0

Najpierw odpowiedz na pytanie: Nie, nie możesz, nie wprost tak, jak chciałeś to zrobić. Może trochę spóźnić się na odpowiedź, ale to jest moje rozwiązanie, bez jQuery, czysty javascript. Pierwotnie został napisany, aby zastosować funkcję zmiany rozmiaru w obszarach tekstowych po załadowaniu DOM i włączeniu go.

W ten sam sposób możesz użyć go do zrobienia czegoś z (wszystkimi) divami lub tylko jednym, jeśli określono, tak:

document.addEventListener("DOMContentLoaded", function() {
    var divs = document.querySelectorAll('div'); // all divs
    var mydiv = document.getElementById('myDiv'); // only div#myDiv
    divs.forEach( div => {
        do_something_with_all_divs(div);
    });
    do_something_with_mydiv(mydiv);
});

Jeśli naprawdę musisz zrobić coś z divem, ładowanym po załadowaniu DOM, np. Po wywołaniu ajax, możesz użyć bardzo pomocnego hacka, który jest łatwy do zrozumienia, a znajdziesz go ... współpracuje z- elementy-przed-the-dom-jest gotowy ... . Mówi „zanim DOM jest gotowy”, ale działa genialnie w ten sam sposób, po wstawieniu ajax lub js-appendChild-cokolwiek z div. Oto kod z niewielkimi zmianami w moich potrzebach.

css

.loaded { // I use only class loaded instead of a nodename
    animation-name: nodeReady;
    animation-duration: 0.001s;
}

@keyframes nodeReady {  
    from { clip: rect(1px, auto, auto, auto); }
    to { clip: rect(0px, auto, auto, auto); }  
}

javascript

document.addEventListener("animationstart", function(event) {
    var e = event || window.event;
    if (e.animationName == "nodeReady") {
        e.target.classList.remove('loaded');
        do_something_else();
    }
}, false);
ddlab
źródło
0

Po załadowaniu pliku HTML z serwera i wstawieniu go do drzewa DOM można go używać, DOMSubtreeModifiedjednak jest on przestarzały - można więc użyć MutationObserverlub po prostu wykryć nową zawartość bezpośrednio w funkcji loadElement, aby nie trzeba było czekać na zdarzenia DOM

Kamil Kiełczewski
źródło
0

Możesz dołączyć detektor zdarzeń, jak poniżej. Uruchamia się, gdy div mający selektor #my-idładuje się całkowicie do DOM.

$(document).on('EventName', '#my-id', function() {
 // do something
});

W takim przypadku nazwa zdarzenia może być „wczytaj” lub „kliknij”

https://api.jquery.com/on/#on-events-selector-data-handler

SkyRar
źródło
-1

Zamiast tego użyj zdarzenia body.onload za pomocą atrybutu ( <body onload="myFn()"> ...) lub poprzez powiązanie zdarzenia w JavaScript. Jest to niezwykle powszechne w przypadku jQuery :

$(document).ready(function() {
    doSomething($('#myDiv'));
});
machać
źródło
javascript czysty, a nie jquery, zaznacz tag;)
KingRider
-3

Spróbuj tego.

document.getElementById("div").onload = alert("This is a div.");
<div id="div">Hello World</div>

Spróbuj tego też. Musisz usunąć .z, oQuickReply.swap()aby funkcja działała.

document.getElementById("div").onload = oQuickReplyswap();
function oQuickReplyswap() {
alert("Hello World");
}
<div id="div"></div>


źródło
Wydaje się, że działa, ale jest po prostu alert("This is a div.");wywoływany, gdy wiersz ten jest wykonywany, a wynik (który jest undefined) jest przypisywany div.onload. Co jest całkowicie bezcelowe.
Frederic Leitenberger,
-4

Nie można dodawać obciążenia zdarzenia dla div, ale można dodać onkeydown i wyzwalać zdarzenie onkeydown podczas ładowania dokumentu

$(function ()
{
  $(".ccsdvCotentPS").trigger("onkeydown");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

<div  onkeydown="setCss( );"> </div>`

Muhammad Bilal
źródło