I clone my mainSection like this (I have to clone it because, there are new elements added to #main over AJAX, and I don't want to search through them):
$mainSection = $('#main').clone(true);
then i search through the cloned main section for an element:
var searchTermHtml = 'test';
$foundElement = $mainSection.filter(":contains('"+searchTermHtml+"')");
When I find the string 'test' in the #mainSection I want to get the original element from it in the $mainSection so I can scroll to it via:
var stop = $foundElementOriginal.offset().top;
window.scrollTo(0, stop);
The question is: how do I get the $foundElementOriginal?
Since you're changing the content of #main after cloning it, using structural things (where child elements are within their parents and such) won't be reliable.
You'll need to put markers of some kind on the elements in #main before cloning it, so you can use those markers later to relate the cloned elements you've found back to the original elements in #main. You could mark all elements by adding a data-* attribute to them, but with greater knowledge of the actual problem domain, I expect you can avoid being quite that profligate.
Here's a complete example: Live Copy
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<meta charset="utf-8">
<title>Example</title>
</head>
<body>
<div id="main">
<p>This is the main section</p>
<p>It has three paragraphs in it</p>
<p>We'll find the one with the number word in the previous paragraph after cloning and highlight that paragraph.</p>
</div>
<script>
(function() {
"use strict";
// Mark all elements within `#main` -- again, this may be
// overkill, better knowledge of the problem domain should
// let you narrow this down
$("#main *").each(function(index) {
this.setAttribute("data-original-position", String(index));
});
// Clone it -- be sure not to append this to the DOM
// anywhere, since it still has the `id` on it (and
// `id` values have to be unique within the DOM)
var $mainSection = $("#main").clone(true);
// Now add something to the real main
$("#main").prepend("<p>I'm a new first paragraph, I also have the word 'three' but I won't be found</p>");
// Find the paragraph with "three" in it, get its original
// position
var originalPos = $mainSection.find("*:contains(three)").attr("data-original-position");
// Now highlight it in the real #main
$("#main *[data-original-position=" + originalPos + "]").css("background-color", "yellow");
})();
</script>
</body>
</html>
Related
I am trying to hide some divs when url contains an specific string.
For example, i have this code that hides the first div:
<div id="ficha">Hello</div>
<div id="ficha">world</div>
<div id="ficha">...</div>
<script>
if (/info|mapo/.test(window.location.href)) {
document.getElementById('ficha').style.display = 'none';
}
</script>
URLs:
www.example.com/all ------> Not hide the div
www.example.com/info-----> Hide the div
www.example.com/mapo---> Hide the div
The first problem with the script is that it only hides the first div saying Hello, but i want to hide all the divs. So, i think it's necessary to do a loop... ¿how can i do that?
The second thing is running two different scripts to hide different divs according the url string content.
Maybe this can be achived by making an else function. Always the loop its necessary and even better if it's executed after load page.
For example:
<div id="ficha">Hello</div>
<div id="ficha">Hello2</div>
<div id="ficha2">world</div>
<div id="ficha2">...</div>
<!-- First script hides divs with id="ficha" if url string has "info" or "mapo" -->
<script>
if (/info|mapo/.test(window.location.href)) {
document.getElementById('ficha').style.display = 'none';
}
</script>
<!-- Second script hides divs with id="ficha2" if url string has "all" -->
<script>
if (/all/.test(window.location.href)) {
document.getElementById('ficha2').style.display = 'none';
}
</script>
The code will be execute in Database Activity of Moodle.
Thanks in advance.
This script will help you.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
window.onload = function () { //The function to execute when the page is loaded
var string_contain = ''; //Set this as your string
var url = window.location.href;
if(url.indexOf(string_contain) >= 0) { //If url contains then...
var x = document.getElementsByClassName("your_class"); //Create an array that contains your divs with your_class class
for(var a = 0;a<x.length;a++) { //Do some stuff for each value of the array
x[a].style.display = 'none';
}
}
}
</script>
</head>
<body>
<div class="your_class"></div>
</body>
</html>
Remeber that the ID is associated with just one element, so it won't work if you're trying to access more than one element.
You've got a few issues here:
First, like user adeneo mentioned in their comment, you cannot share IDs. Classes, however, can be shared so you probably want your <div> elements to say class="ficha".
Second, you want to hide or show divs based off of a string in the URL, but your URLs are composed of unique paths. You're trying to hide divs, when you should just be building the pages differently. Unless there's more information you need to add about this.
www.example.com/mapo is, at least in the representation you've provided, a different HTML page from www.example.com/info so why not build them as separate pages rather than going through unnecessary logic to show and hide <div> elements?
The third issue: you don't want a for loop so much as a for-each loop. This first question will give you direction on how to select all elements with the specified class:
JavaScript get elements by class name and tag name
Then using the array you've selected from the above information, you can use Javascript Documentation for using forEach on arrays to change your elements' visibility.
Since its not unique, a CSS class would be more appropriate. Something like this should work:
function hideItemsByClass(className){
var matchedItems = document.getElementsByClassName(className);
for(var i = 0; i < matchedItems.length; i++){
matchedItems[i].style.display = 'none';
}
}
So I have this JS code :
var pElt = document.createElement("p");
var aElt = document.createElement("a");
aElt.textContent = "Text";
aElt.href = "#";
pElt.appendChild(aElt);
aElt.style.color = "red";
pElt.innerHTML += "<span> and more text</span>";
//aElt.style.color = "red";
document.getElementById("content").appendChild(pElt);
console.log(aElt); // always show the red attribute
There's probably some answer around here, but I cannot even describe the problem ; so I went with "losing node reference", even though it's not what happens here. (edit: in fact, that's what happens here, silly :))
So... Please try the code as it is. It works, the link is red, everyone is happy. Now comment the "aElt.style.color = "red";" line, then uncomment the other one, two lines below.
...
It does not work, the link still appear in black. What I thought is that the pointer linked to my node was either not valid anymore or the aElt was moved to a different memory address. But when I type "console.log(aElt)", it outputs the node correctly (well... I think it does), so I don't get why I can't access it after the .innerHTML change.
What interests me is what happens under the hood :)
Thanks!
index.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Question!</title>
</head>
<body>
<div id="content"></div>
<script src="script.js"></script>
</body>
</html>
When you overwrite the content of the <p> element by setting it's innerHTML, you're effectively turning the <a> back into HTML text, appending the <span> (as text), and then recreating new DOM nodes in the <p>. Your old reference still refers to the original <a> you created.
You could instead create that <span> the same way you created the <a>, and append that node to the <p> instead of overwriting .innerHTML.
This is going to be hard to explain but I will do my best. I want to write a Javascript function that takes two parameters (title, content) and creates a <div> tag in the <body> tag. The <div> tag should look like this.
<div>
<h2>title</h2>
<p>content</p>
</div>
My javascript code looks like this:
function addElement (title, content) {
var newDiv = document.createElement("div");
var newH2 = document.createElement("h2");
var title = document.createTextNode(header);
newH2.appendChild(title);
var p = document.createElement("p");
var post = document.createTextNode(entry);
p.appendChild(post);
newDiv.appendChild(newH2);
newDiv.appendChild(p);
// Missing codes here...
}
I dont know how to finish my method. Because of I have almost hundreds of tags inside my page and I want this new tags (when a user makes a new input) will appear on same place somewhere in the middle of the html code page in order to keep things organized.
If you would like to use jQuery take a look at this fiddle: http://jsfiddle.net/panpymq2/
In my fiddle I am binding to a button press. Then I call a method that appends new generated html to the body of the page. You can enter change where you are appending the new HTML with CSS3 selectors. just modify the $("insert selector there").append...
UPDATE
As per the new requirements I have updated my fiddle: http://jsfiddle.net/panpymq2/1/
I now prepend the new html to the document.
You already know how to add elements as children of other elements. That's what you used to add the h2 and p to the div. You could use the same appendChild to add the div to the document:
document.body.appendChild(newDiv);
But you don't want it at the bottom of the page--you want it "in the middle of the html code page". One straightforward way to do this is to add the newDiv to a container that's in the right place, in the middle of the page.
You'd first create this container in the page HTML:
<!doctype html>
<body>
<p>stuff before</p>
<div id="container"></div>
<p>stuff after</p>
</body>
Then, finish off addElement with:
document.getElementById('container').appendChild(newDiv);
One way would be if addElement took a third parameter which is the sibling/parent you want to insert your new element next to/within.
function addElement(title, content, target) {
...
target.insertAdjacentElement('afterend', newDiv);
// or
target.appendChild(newDiv);
}
I think this is as much of an HTML as a CSS problem. I've had the same issue.
One way of solving this problem is to make an (extra) container <div> as follows:
<div id="outer_container_elems">
<div id="inner_container_elems">
...
</div>
</div>
And append to inner_container_elems
Hope this helps!
this has been driving me crazy since yesterday afternoon. I am trying to concatenate two bodies of selected HTML using jQuery's "add" method. I am obviously missing something fundamental. Here's some sample code that illustrated the problem:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<p id="para1">This is a test.</p>
<p id="para2">This is also a test.</p>
<script>
var para1 = $("#para1").clone();
var para2 = $("#para2").clone();
var para3 = para1.add(para2);
alert("Joined para: " + para3.html());
para3.appendTo('body');
</script>
</body>
</html>
I need to do some more manipulation to "para3" before the append, but the alert above displays only the contents of "para1." However, the "appendTo appends the correct, "added" content of para1 and para2 (which subsequently appears on the page).
Any ideas what's going on here?
As per the $.add,
Create a new jQuery object with elements added to the set of matched elements.
Thus, after the add, $para3 represents a jQuery result set of two elements ~> [$para1, $para2]. Then, per $.html,
Get the HTML contents of the first element in the set of matched elements or set the HTML contents of every matched element.
So the HTML content of the first item in the jQuery result ($para1) is returned and subsequent elements (including $para2) are ignored. This behavior is consistent across jQuery "value reading" functions.
Reading $.appendTo will explain how it works differently from $.html.
A simple map and array-concat can be used to get the HTML of "all items in the result set":
$.map($para3, function (e) { return $(e).html() }).join("")
Array.prototype.map.call($para3, function (e) { return $(e).html() }).join("")
Or in this case, just:
$para1.html() + $para2.html()
Another approach would be to get the inner HTML of a parent Element, after the children have been added.
In the below code, I commented A and B at each lines.
What is the different between A and B? And which is recommended?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<template id="templatetest">
<div>test</div>
</template>
<body></body>
<script type="text/javascript">
var t = document.querySelector('#templatetest');
var n = document.importNode(t.content, true);
document.body.appendChild(n); //A
document.body.appendChild(t.content); //B
</script>
</html>
And one more question..
The above code renders two "test"s. But when I switch positions of A and B like the below code, only one "test" is rendered somehow. I would like to know why this happens.
<script type="text/javascript">
var t = document.querySelector('#templatetest');
document.body.appendChild(t.content); //B
var n = document.importNode(t.content, true);
document.body.appendChild(n); //A
</script>
The points is importNode creates a copy of the node and returns it, then you can add it in a new parent using appendChild. It's intended to be used when you're getting nodes from anoother documents and inserting it in your doc (for example, when you're moving nodes between different XML files), this function will fix things like the ownerDocument property and other internal things I believe.
The appendChild just to append nodes to other nodes, if the node you is appending is already a child of any other node, first it will remove it from there and move it to its new parent.
In your first example:
A - you create a copy of t.content (n - importNode) and append it to the body;
B - you just append t.content to body, thus removing it from it's original parent
Your second example
B - You moves the content of #templatetest to the body
A - #templatetest is now empty, it has no more content, so there is nothing to you copy and append in your body anymore