The following code is throwing the error "this.element is null". However, the wid_cont is definitely grabbing an element.
window.addEvent('domready',function(){
var min = $(document.body).getElements('a.widget_minimize');
min.addEvent('click',
function(event){
event.stop();
//var box = ;
var wid_cont = ($(this).getParents('.widget_box').getElement('.widget_box_content_cont'));
var myVerticalSlide = new Fx.Slide(wid_cont);
myVerticalSlide.slideOut();
}
);
});
It's moo tools 1.2.4 and has the fx.slide included....
it does not return a single element but an array due to getParents() and possible other similarly marked up elements, Fx.Slide requires you pass it a single element.
here it is at least partially working when passing first item of the array: http://www.jsfiddle.net/KFdnG/
however, this is imo ineffective and difficult to manage if you have a long list of items and need a particular content layer to unfold only, you want to keep the lookup to the content layer more local.
something like this:
http://www.jsfiddle.net/KFdnG/4/
// store an instance into each content div and set initial state to hidden.
$$("div.widget_box_content_cont").each(function(el) {
el.store("fxslide", new Fx.Slide(el).hide());
});
$$('a.widget_minimize').addEvent('click', function(event) {
event.stop();
// can't use this.getNext() due to wrapper by Fx.Slide which does not have the instance.
this.getParent().getElement("div.widget_box_content_cont").retrieve("fxslide").toggle();
});
which works on the markup of:
<div class="widget_box">
<div class="widget_box_content">
link
<div class="widget_box_content_cont">
some content
</div>
</div>
<div class="widget_box_content">
link 2
<div class="widget_box_content_cont">
some content 2
</div>
</div>
</div>
this is also better as you won't be making a new instance of the Fx.Slide class on every click but will reference the ones already attached to the element.
Related
Consider a UI that has a custom component <foo>- for now assume its just text.
<foo id="foo-id">SOMETEXT</foo>
I'd like to display this content in two places on the UI - one of which is in a modal. How can I have the modal content delegate to this existing element? I'm using open to Jquery/angularjs or native HTML solutions.
<foo id="foo-id">SOMETEXT</foo>
<div class="modal fade" id="exampleModal" ...>
...
<div class="modal-body">
### REFERENCE TO ID #foo-id here ###
</div>
</div
I'm trying to avoid using a second instance of the element, eg:
<foo id="foo-id">SOMETEXT</foo>
<div class="modal fade" id="exampleModal" ...>
...
<div class="modal-body">
<foo id="foo-id-2">SOMETEXT</foo>
</div>
</div
More Context
The reason I actually want to do this is because we have a webpage with a dropdown expander that already renders rich components. We're trying to add a "popout" button that would display the rendered element in a modal window. Because the elements are already in the correct loaded state at the time of popout being pressed, then it makes sense to just delegate the component to a pre-defined one rather than recreating.
Stack is angularJS, bootstrap 3, jquery and I cannot change this :(
The way I would do it in vanilla javascript is creating a function that creates a modal element and then append it to the DOM element you want e.g. the body.
An example:
function createModal(modalId, fooElement){
const modalDiv = document.createElement('div');
modalDiv.classList.add('modal');
modalDiv.classList.add('fade');
modalDiv.id = modalId;
const modalBodyDiv = document.createElement('div');
modalBodyDiv.classList.add('modal-body');
modalBodyDiv.append(fooElement);
return modalDiv;
}
And then use it to create N modal elements and append them wherever you want e.g. the body, like this:
const modal1 = createModal('myModal1', fooElement);
document.body.append(modal1)
This way your html will be cleaner.
Note: this fooElement must be a DOM element, otherwise it will throw an error.
Hope it works!
if you not need have two copy you could try detach the element and insert it at his new place
let $fooContent = $("#foo-id");
let $myModal = $("#exampleModal > .modal-body");
...
// set it
$myModal.html( $fooContent.detach() );
// back it
$initialFooContentLocation.append( $fooContent.detach() );
The accepted answer worked for me; however, for completeness here's another approach.
Use $scope/$rootScope event emitters to broadcast events between components. If the components have a clear parent/child relationship, $scope is usually adequate and if they are siblings, then they can share events via $rootScope.
Since this is an angularJS project, I followed this simple guide.
In the past I used Google Developer Console to delete some specific divs on a page. I could do it manually of course but in some cases where the divs where many I had to use the console. I had a single line code that did the job (I found it while searching the internet) but I lost my note.
So how can I delete using javascript any html code (by copy pasting the code).
Something like:
elements = $('<div ... </div>');
elements.remove();
OR
$('<div ... </div>').remove();
Any ideas? I am not an expert in javascript (obviously) and I've been searching stackoverflow for hours without finding anything that works.
UPDATE: I think some people might get confused with my question. Google developer console accepts javascript command lines. So even though I ask for javascript I will use the code on the google developer console.
UPDATE 2 :
Here is an example of a div I need to delete. Keep in mind I want to copy paste the entire code in the javascript code. Not just identify the div.
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
It's the data-entry-status="declined" that makes that div unique so I can't just identify the div using an id selector or a class selector. I need to put the entrire thing there and remove it.
I tried:
$('<div class="entry-status-overlay" data-entry-status="declined"><div class="entry-status-overlay__inner"><span class="entry-status-overlay__title">Declined</span></div></div>').remove();
It didn't remove the div.
Try to search the dom by its outerHTML.
function deleteDomByHtml(html){
html=html.replace(/\s/g,'');
$("*").each(function(){
if(this.outerHTML.replace(/\s/g,'')===html){
$(this).remove();
}
});
}
And try this line on this page:
deleteDomByHtml(`<span class="-img _glyph">Stack Overflow</span>`);
You cannot do by simply pasting the code. That will remove all the div element.
You may need a specific selector like id,class or child to specific parent to remove the element from the dom.
Consider this case the divs have common class but the data-entry-status is different. So you can get the dom using a selector and then check the dataset property.
For demo I have put it inside setTimeout to show the difference. In application you can avoid it
setTimeout(function() {
document.querySelectorAll('.entry-status-overlay').forEach(function(item) {
let getStatus = item.dataset.entryStatus;
if (getStatus === 'declined') {
item.remove()
}
})
}, 2000)
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div class="entry-status-overlay" data-entry-status="accepted">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">accepted</span>
</div>
</div>
Just add any attribute with [] and it will remove the element.
$('[class="entry-status-overlay"]').remove();
/*OR*/
$('[data-entry-status="declined"]').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
function del(){
var h = document.body.outerHTML;
h = h.match('<div>...</div>');
h.length--;
return h;
}
I guess this will work just give it a try... i tried on browser console and it worked, this way you can match the exact you want.
I might as well add my take on this. Try running this in your console and see the question vanish.
// convert the whole page into string
let thePage = document.body.innerHTML,
string = [].map.call( thePage, function(node){
return node.textContent || node.innerText || "";
}).join("");
// I get some string. in this scenario the Question or you can set one yourself
let replacableCode = document.getElementsByClassName('post-layout')[0].innerHTML,
string2 = [].map.call( replacableCode, function(node){
return node.textContent || node.innerText || "";
}).join("");
// replace whole page with the removed innerHTML string with blank
document.body.innerHTML = thePage.replace(replacableCode,'');
If you want to identify divs with that particular data attribute, you can use a data-attribute selector. In the example below, I've used a button and click event to make the demo more visual, but in the console the only line you'd need would be:
$('div[data-entry-status="declined"]').remove();
$(function() {
$("#testbutton").click(function() {
$('div[data-entry-status="declined"]').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div id="x">Some other div</div>
<button type="button" id="testbutton">Click me to test removing the div</button>
See https://api.jquery.com/category/selectors/attribute-selectors/ for documentation of attribute selectors.
P.S. Your idea to paste some raw HTML into the jQuery constructor and then execute "remove" on it cannot work - you're telling jQuery to create an object based on a HTML string, which is, as far as it's concerned, a new set of HTML. It does not try to match that to something existing on the page, even if that exact HTML is in the DOM somewhere, it pays it no attention. It treats what you just gave it as being totally independent. So then when you run .remove() on that new HTML...that HTML was never added to the page, so it cannot be removed. Therefore .remove() has no effect in that situation.
I have an unexpected problem.
HTML
<div id="div1" class="myDiv"></div>
<div id="div2" class="myDiv"></div>
<div id="div3" class="myDiv"></div>
<div id="div5" class="myDiv"></div>
<div id="div6" class="myDiv"></div>
JS
$(function() {
var $divs = $('.myDiv');
// create new div not in tree
var $div = $('<div/>').attr("id","div4").addClass('myDiv');
// insert #div4 in right position. Only in stack, not in dom tree.
$divs = $divs.slice(0,3).add($div).add($divs.slice(3));
console.log($divs);
});
output
[div#div1.myDiv, div#div2.myDiv, div#div3.myDiv, div#div5.myDiv, div#div6.myDiv, div#div4.myDiv]
Warning: I DON'T want to insert it in dom tree (like $div.appendBefore($divs[3])), I just want append it in my stack $divs.
I thought that this stack was an ordered list. So, my goal was to create on fly a #div4 and insert it in $divs stack without insert it in DOM tree. The insert works but it seems that jquery ignore the order given.
I've other solutions for this problem (i.e. append in dom with a display none), ok.. but:
My question is: why? It's a bug for some cache optimization, or it's a documented feature?
I've also tried:
var $newDivs = $();
$divs.each(function(i,e) {
if(i==3)
$newDivs = $newDivs.add($div);
$newDivs = $newDivs.add(e);
});
console.log($newDivs);
but the output is the same.
EDIT: Just for completeness: this was just a fast hack for a complex code. I know that the purpose is not clean
That's not the purpose of a jQuery object. KEep your data-structures straight; I'm not sure how the concept of a 'stack' came into this at all. Use the regular built in JS arrays (which keep items ordered):
$(function() {
// make an array of existing divs
var divs = $('.myDiv').toArray();
// create new div
var newDiv = $('<div/>').attr("id","div4").addClass('myDiv').get(0);
// insert newDiv at index 4 in array
divs.splice(4, 0, newDiv);
// Rejoice.
console.log(divs);
});
One more variant of nbrooks answer
// get regular array of matched DOM nodes
var divs = $('.myDiv').toArray();
// require you to find out on which position you need to put your new div
divs.splice(2, 0, $('<div/>').attr("id","div4").addClass('myDiv').get(0))
// again wrap in jQuery to get what you need
divs = $(divs);
As of jQuery 1.4 the results from .add() will always be returned in document order (rather than a simple concatenation).
It's documented behaviour, it's not a normal array.
http://api.jquery.com/add/
Really seems not a jquery behaviour but more a javascript browser's native code implementation as
i get these results, depending of which browser is used (windows7):
Firefox and IE9: 1,2,3,5,6,4
Safari : 1,2,3,4,5,6
Chrome: 4,1,2,3,5,6
I have created a view in Drupal. I'm using JavaScript to modify the CSS in each row. The script runs on the first row, but does not make the changes on the rest of rows from the view.
This is the script:
<script language="javascript" type="text/javascript">
window.onload = floatbr;
function floatbr() {
var f = document.getElementById('firstright') // Get div element
var s = document.getElementById('secondright') // Get div element
var w = document.getElementById('catwrapper') // Get div element
var sh = s.offsetHeight // secondright div height
var wh = w.offsetHeight // catwrapper div height
f.style.height = wh - sh + 'px'; }
</script>
I'm using it from this page: http://agsone.100webcustomers.com/floatbottom.php
having the script in the page once does not do the trick.
having the script in the view footer and repeating the script does not work.
The link to the jSfiddle with HTML, CSS and JavaScript is the following one: http://jsfiddle.net/YTN3K/.
Drupal provides and already uses jQuery, so you should use it too. Drupal has its own way to manage JavaScript and comes with some additional JavaScript API, mainly to handle passing variables from PHP to JavaScript properly, register script to run on page load and content addition, etc.
jQuery is well documented and popular, so finding documentation, tutorial and howto is easy. Its own documentation page is a good start. But it requires basic understanding of what an XHTML document is and how it is structured.
It's hard to tell from your question and the markup you've linked to exactly what you're trying to do, so here's some general information to get you going:
The function you're currently using, getElementById, returns a single element: The one on the page with that id value. (id values must be unique on the page.)
To deal with multiple elements, you have several options. Two of the most popular:
You can start with a given element and then use its childNodes, firstChild, nextSibling, and similar properties to navigate from it to other elements nearby.
You can use getElementsByTagName (on the document or on an element) to find all elements within that container (including ones several levels down) that have a given tag. For instance, document.getElementsByTagName("p") gives you a NodeList of all paragraphs on the page.
These are properties and methods of the "DOM" (the Document Object Model), which is the tree of elements and associated information the browser creates when parsing and rendering your HTML.
References:
DOM2 Core
DOM2 HTML bindings
DOM3 Core
HTML5 Specification's DOM info
Here's an example showing some very basic operations (live copy):
HTML:
<div id="justOneDiv">I'm the <code>justOneDiv</code> element. I'm unique on the page. JavaScript code on the page turned me red.</div>
<div id="container">I'm a container called "container" with <span>various</span> <code>span</code> elements. <span>Code</span> on the <span>page</span> has made all of the <code>span</code> elements in this container <span>bold</span>.</div>
<div>I'm a container with <span>various</span> <code>span</code> elements. <span>Note</span> that the <code>span</code> elements are <span>not</span> bold, because I'm <span>not</span> in the container above.</div>
<div>I'm a <code>div</code> with no class.</div>
<div class="foo">I'm a <code>div</code> with class "foo". Code on the page turned me blue.</div>
<div class="bar">I'm a <code>div</code> with class "bar". Code on the page turned me green.</div>
<div>Another classless <code>div</code></div>
<div class="foo other">Another "foo", also with class "other"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar test">Another "bar", also with class "test"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
JavaScript:
(function() {
hookEvent(window, "load", go);
function go() {
var list, index, div, container;
// Get just the one element, turn it red
document.getElementById("justOneDiv").style.color = "red";
// Get the spans within the specific container
container = document.getElementById("container");
list = container.getElementsByTagName("span");
// Loop through making those spans bold
for (index = 0; index < list.length; ++index) {
list.item(index).style.fontWeight = "bold";
}
// Get a NodeList of all divs on the page
list = document.getElementsByTagName("div");
// Loop it, turning "foo"s blue and "bar"s green
for (index = 0; index < list.length; ++index) {
div = list.item(index);
if (/\bfoo\b/.test(div.className)) {
div.style.color = "blue";
}
else if (/\bbar\b/.test(div.className)) {
div.style.color = "green";
}
}
}
function hookEvent(element, eventName, handler) {
// Very quick-and-dirty, recommend using a proper library,
// this is just for the purposes of the example.
if (typeof element.addEventListener !== "undefined") {
element.addEventListener(eventName, handler, false);
}
else if (typeof element.attachEvent !== "undefined") {
element.attachEvent("on" + eventName, handler);
}
else {
element["on" + eventName] = handler;
}
}
})();
Side note: The operations above can be made dramatically simpler by leveraging the utility functionality provided by any decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others.
For example, using that same HTML, here's the JavaScript code using jQuery for the same result (live copy):
jQuery(function($) {
// Get just the one element, turn it red
$("#justOneDiv").css("color", "red");
// Get the spans within the specific container
// Loop through making those spans bold
$("#container span").css("font-weight", "bold");
// Turn all divs with the class "foo" blue
$("div.foo").css("color", "blue");
// Turn all divs with the class "bar" green
$("div.bar").css("color", "green");
});
The DOM is the official API; libraries like jQuery provide alternate or enhanced APIs. They're very useful and powerful, but I would recommend having some understanding of the DOM itself, even if you use a library and end up rarely writing code directly to the DOM API.
Problem:
Extract all html between two headers including the headers html. The header text is known, but not the formatting, tag name, etc. They are not within the same parent and might (well, almost for sure) have sub children within it's own children).
To clarify: headers could be inside a <h1> or <div> or any other tag. They may also be surrounded by <b>, <i>, <font> or more <div> tags. The key is: the only text within the element is the header text.
The tools I have available are: C# 3.0 utilizing a WebBrowser control, or Jquery/Js.
I've taken the Jquery route, traversing the DOM, but I've ran into the issue of children and adding them appropriately. Here is the code so far:
function getAllBetween(firstEl,lastEl) {
var collection = new Array(); // Collection of Elements
var fefound =false;
$('body').find('*').each(function(){
var curEl = $(this);
if($(curEl).text() == firstEl)
fefound=true;
if($(curEl).text() == lastEl)
return false;
// need something to add children children
// otherwise we get <table></table><tbody></tbody><tr></tr> etc
if (fefound)
collection.push(curEl);
});
var div = document.createElement("DIV");
for (var i=0,len=collection.length;i<len;i++){
$(div).append(collection[i]);
}
return($(div).html());
}
Should I be continueing down this road? With some sort of recursive function checking/handling children, or would a whole new approach be better suited?
For the sake of testing, here is some sample markup:
<body>
<div>
<div>Start</div>
<table><tbody><tr><td>Oops</td></tr></tbody></table>
</div>
<div>
<div>End</div>
</div>
</body>
Any suggestions or thoughts are greatly appreciated!
My thought is a regex, something along the lines of
.*<(?<tag>.+)>Start</\1>(?<found_data>.+)<\1>End</\1>.*
should get you everything between the Start and end div tags.
Here's an idea:
$(function() {
// Get the parent div start is in:
var $elie = $("div:contains(Start)").eq(0), htmlArr = [];
// Push HTML of that div to the HTML array
htmlArr.push($('<div>').append( $elie.clone() ).html());
// Keep moving along and adding to array until we hit END
while($elie.find("div:contains(End)").length != 1) {
$elie = $elie.next();
htmlArr.push($('<div>').append( $elie.clone() ).html());
};
// htmlArr now has the HTML
// let's see what it is:
alert(htmlArr.join(""));
});
Try it out with this jsFiddle example
This takes the entire parent div that start is in. I'm not sure that's what you want though. The outerHTML is done by $('<div>').append( element.clone() ).html(), since outerHTML support is not cross browser yet. All the html is stored in an array, you could also just store the elements in the array.