Content Editable button in Javascript apply to a class - javascript

My goal here is to make multiple divs editable by the click of a button. Is there a way to do this by using a class instead of an ID? I'd like to be able to add the editable class to multiple divs throughout my site. Is there a plugin or module that would be well suited for this task? I don't want to edit the code or formatting in the browser, the text content only.
Your thoughts?
test test test test1
test test test test2
test test test test3
<script>
var editorBtn = document.getElementsByClassName('editBtn');
var element = document.getElementsByClassName('editable');
editorBtn.addEventListener('click', function(e) {
e.preventDefault();
if (element.isContentEditable) {
element.contentEditable = 'false';
editBtn.innerHTML = 'update';
} else {
element.contentEditable = 'true';
editBtn.innerHTML = 'done';
}
});
</script>

getElementsByClassName is going to return an array. You probably want to access your button via ID, and the elements via class.
<script>
var editorBtn = document.getElementById('editBtn');
editorBtn.addEventListener('click', function(e) {
e.preventDefault();
var elements = document.getElementsByClassName('editable');
for(var i =0;i<elements.length;i++){
if (elements[i].isContentEditable) {
elements[i].contentEditable = 'false';
editBtn.innerHTML = 'update';
} else {
elements[i].contentEditable = 'true';
editBtn.innerHTML = 'done';
}
}
});
</script>
you should probably pull the editBtn.innerHTML outside the loop, but, since you are making them all editable, or all not editable, it should work as desired as-is.
Add 'editable' class to to your hearts content.
Edit: The above is just an example of how to modify attributes to elements with a given class name (editable). Whether the attributes you are modifying will achieve your desired goal of making the element allow/prohibit editing, is not guaranteed.

If you want to add a class to a set of divs or elements, use Jquery
$(".classToSelect").addClass("classToInsert")
If this is not what you want, plz clarify your question

Related

How do I target siblings in vanilla javascript?

I'm creating a toggle review form that displays when you hit Edit, but I only want this to work on on the review the button is a sibling of, as opposed to all review edit forms on the page (as there may be multiple).
I know how to do this in jquery but am trying to keep this project all vanilla js.
const button = document.querySelector('.toggle-edit-form');
const form = document.querySelector('.edit-review-form');
button.onclick = function() {
// toggle the edit button text on click
button.innerHTML === 'Edit' ? button.innerHTML = "Cancel" : button.innerHTML = "Edit";
// toggle visibility of edit review form
form.classList.toggle('toggle')
};
I could use nextSibling I suppose (as it is currently the next sibling) but would prefer a solution that won't break the code if change the order / html.
Thanks!
#Mike you can try creating a function that uses a while loop to keep track of siblings , I hope this helps
var getSiblings = function (elem) {
// Setup siblings array and get the first sibling
var siblings = [];
var sibling = elem.parentNode.firstChild;
// Loop through each sibling and push to the array
while (sibling) {
if (sibling.nodeType === 1 && sibling !== elem) {
siblings.push(sibling);
}
sibling = sibling.nextSibling
}
return siblings;
};

Javascript don't add the class

hello everyone javascript don't add the class to html
$(".ocmessage").each(function(){
var text = $(this).find('p').html();
if(strpos(text,"<b>"+name+"</b>")!==false) $(this).addClass("quoteme");
});
this code should detect if in <p>...</p> there are name of some member and if there is javascript should add class quoteme
how can i fix it?
I think you mean this. BTW, name isn't defined.
var name = ''; // change the value
if(text.indexOf("<b>"+name+"</b>") > -1) {
$(this).addClass("quoteme");
}
Assuming ocmessage is a div or another contain class.
Take a look at : http://jsfiddle.net/40vv7dbk/
$(".ocmessage").each(function () {
var $this = $(this);
var text = $this.find('p').html();
var name = "Ben"
// Will be -1 if not found.
if (text.indexOf(name) > -1) {
$this.addClass("quoteme");
}
});
What it is doing, is when the document is ready, going through all the Divs with the class ocmessage, looking for a tag, and then checking if a name is in there. If it does, I add the class quoteme.
Your elements with class ocmessage may contain more than one paragraph. So inside the first each-loop we have to do a second loop through all <p> like so:
$(".ocmessage").each(function(){
var $T = $(this);
$T.find('p').each(function() {
var text = $(this).html();
// find username and prevent multiple class adding
if(text.indexOf("<b>"+name+"</b>") > -1) {
$T.addClass("quoteme"); return false; // stop loop when class is added
}
});
});
Working FIDDLE here. Credits to Amit Joki.
This is a very poor way to accomplish the task. Here's the more standard jquery way to do it.
$(".ocmessage").has('p b:contains('+name+')').addClass("quoteme");

javascript choose what is going to include element

I have two elements, the first one is the default to print on screen
<input id=post-category value="first">
and the other is this, which will only show if some onclick was made and of course the first element must show off
<select id=cat-sel ><option>second</option></select>
UPDATED
I tried this code
el = document.getElementById("post-category");
el.style.visibility = "hidden";
el2 = document.getElementById("cat-sel");
el2.style.visibility = "visible";
but the problem here is, the 2nd element is indented. because it escapes the space for the 1st element. I don't like that, I wanted them to be on the same position
Change to
el = document.getElementById("post-category");
el.style.display = "none";
el2 = document.getElementById("cat-sel");
el2.style.display = "block";
since visible/hidden does not remove the space the element takes up on the page
You need to set display:none on the field you need to hide initially
Assuming a checkbox have
window.onload=function() {
document.getElementById("categoryCheckbox").onclick=function() {
var chk = this.checked;
document.getElementById("post-category").style.display = chk?"none":"block";
document.getElementById("cat-sel").style.display = chk?"block":"none";
}
}
PS: A little more code is needed for the show/hide to survive a reload by the way...
Define CSS for your ID's and fix the position.

confusion in jquery parents selector with hasClass function

var allChecked = $('.inboxCheckbox:checked');
if(allChecked.length > 0){
var messageIds = new Array();
var parentRow = null;
allChecked.each(
function(){
parentRow = $(this).parents('tr');
if(!(parentRow.hasClass('gradeA'))){
parentRow.addClass('gradeA');
increaseUnreadMessage();
}
parentRow = null;
messageIds.push($(this).val());
}
);
}else{
showInsMessage('<b class="redTxt">Please Select At Least One Message</b>');
}
i have multiple rows with once checkbox in each row... i was trying to add class gradeA to each row if checkbox is checked.... i do not want to call addClass if it already has class gradeA.... when i select multiple rows then it adds class to only one row. does that mean
lets say i have three rows with checkbox in each row and i select each checkbox when i run
$(':checked').each(
$(this).parents('tr')
)does it select all the rows with checked boxes or only the specfic parent row.... my assuption was it only gives the specific parent row..... if it gives specific row then it should work .. but once i add a class to parent row and move to another row then parentRow.hasClass('gradeA') return true... i am confused now if it checks all the row with checkboxes then is there any way to select specific parent row......
Thanks for reading
Would be nice to see the markup, are there more tables nested?
However,
parentRow = $(this).closest('tr');
should be a better choice.
API says that .parents() method search through all ancestors of the elements.
.parent() travels only a single level up the DOM tree.
If your checkbox is a direct child (not a deep descendant) of 'tr' then you can try
parentRow = $(this).parent('tr');
Your code should work. I suspect that the problem is happening because your function increaseUnreadMessage() is throwing an error, which is causing the rest of the each() loop to be skipped.
But, to answer your specific question: yes, you can select all rows (<td>s) that contain checked checkboxes. Using jquery's :has selector, like this:
var allCheckedRows = $('tr:has(.inboxCheckbox:checked)');
from there, of course, you can just use addClass() to apply your classname to all of them:
allCheckedRows.addClass('gradeA');
of course, you've got other things going on in your each() loop, so you probably can't throw out the each() entirely. As I said above, your code works... but something like this might be cleaner, and easier to understand.
var messageIds = new Array();
var allCheckedRows = $('tr:has(.inboxCheckbox:checked)');
allCheckedRows.addClass('gradeA');
allCheckedRows.find('.inboxCheckbox').each( function() {
var cb = $(this);
increaseUnreadMessage();
messageIds.push( cb.val() );
});
if( messageIds.length === 0 ) {
showInsMessage('<b class="redTxt">Please Select At Least One Message</b>');
}
BTW, I think you can do it more jQuerish style :
var messageIds = [];
$('tr.youTrs').toggleClass('gradeA', function () {
var checkbox = $(this).find('.inboxCheckbox');
if (checkbox.is(':checked')){
messageIds.push(checkbox.val());
return true;
}
else{
showInsMessage('<b class="redTxt">Please Select At Least One Message</b>');
return false;
}
});

How are they doing the accordion style dropdown on the following website?

I was taking a look at http://www.zenfolio.com/zf/features.aspx and I can't figure out how they are doing the accordion style expand and collapse when you click on the orange links. I have been using the Web Developer Toolbar add-on for firefox, but I have not been able to find anything in the source of the page like JavaScript that would be doing the following. If anyone knows how they are doing it, that would be very helpful.
This is actually unrelated, but if all you answers are good, who do I give the answer too?
They're setting the .display CSS property on an internal DIV from 'none' to '', which renders it.
It's a bit tricky, as the JS seems to be in here that's doing it:
http://www.zenfolio.com/zf/script/en-US/mozilla5/windows/5AN2EHZJSZSGS/sitehome.js
But that's basically how everyone does this. It's in there, somewhere.
EDIT: Here it is, it looks like:
//... (bunch of junk)
zf_Features.prototype._entry_onclick = function(e, index)
{
var cellNode = this.dom().getElementsByTagName("H3")[index].parentNode;
while (cellNode.tagName != "TD") cellNode = cellNode.parentNode;
if (this._current != null) this.dom(this._current).className = "desc";
if ("i" + index != this._current)
{
cellNode.className = "desc open";
cellNode.id = this.id + "-i" + index;
this._current = "i" + index;
}
else this._current = null;
zf_frame.recalcLayout();
return false;
};
Basically, what they're doing is a really roundabout and confusing way of making the div inside of TD's with a class "desc" change to the class "desc open", which reveals its contents. So it's a really obtuse roundabout way to do the same thing everyone does (that is, handling onclick to change the display property of a hidden div to non-hidden).
EDIT 2:
lol, while I was trying to format it, others found it too. =) You're faster than I ;)
Using jQuery, this effect can be built very easily:
$('.titleToggle').click(function() {
$(this).next().toggle();
});
If you execute this code on loading the page then it will work with any markup that looks like the following:
<span class="titleToggle">Show me</span>
<div style="display:none">This is hidden</div>
Notice that this code will work for any number of elements, so even for a whole table/list full of those items, the JavaScript code does not have to be repeated or adapted in any way. The tag names (here span and div) don't matter either. Use what best suits you.
It is being done with JavaScript.
When you click a link, the parent td's class changes from 'desc' to 'desc open'. Basically, the expanded text is always there but hidden (display: none;). When it gets the css class of 'open' the text is no longer being hidden (display: block;).
If you look in the sitehome.js and sitehome.css file you can get an idea about how they are doing that.
btw I used FireBug to get that info. Even though there is some feature duplication with Web Developer Toolbar it's worth the install.
They're using javascript. You can do it too:
<div id="feature">
Feature Name
<div id="desc" style=="display:none;">
description here...
</div>
</div>
<script type="text/javascript">
function toggle()
{
var el=document.getElementById('desc');
if (el.style.display=='none')
el.style.display='block'; //show if currently hidden
else
el.style.display='none'; //Hide if currently displayed
}
</script>
The function above can be written using Jquery for smooth fade in/fade out animations when showing/expanding the descriptions. It has also got a SlideUp and Slidedown effect.
There is a lot of obfuscated/minified JS in their master JS include. It looks like they are scraping the DOM looking for H3's and checking for table cells with class desc and then processing the A tags. ( or some other order, possibly ) and then adding the onclick handlers dynamically.
if (this._current != null) this.dom(this._current).className
= "desc"; if ("i" + index != this._current) { cellNode.className = "desc open"; cellNode.id = this.id
+ "-i" + index; this._current = "i" + index; }
http://www.zenfolio.com/zf/script/en-US/safari3/windows/5AN2EHZJSZSGS/sitehome.js
The script is here.
The relevant section seems to be (re-layed out):
// This script seems over-complicated... I wouldn't recommend it!
zf_Features.prototype._init = function()
{
// Get a list of the H3 elements
var nodeList = this.dom().getElementsByTagName("H3");
// For each one...
for (var i = 0; i < nodeList.length; i++)
{
// ... set the onclick to be the function below
var onclick = this.eventHandler(this._entry_onclick, i);
// Get the first <a> within the H3 and do the same
var node = nodeList[i].getElementsByTagName("A")[0];
node.href = "#";
node.onclick = onclick;
// And again for the first <span>
node = nodeList[i].getElementsByTagName("SPAN")[0];
node.onclick = onclick;
}
};
zf_Features.prototype._entry_onclick = function(e, index)
{
// Get the parent node of the cell that was clicked on
var cellNode = this.dom().getElementsByTagName("H3")[index].parentNode;
// Keep going up the DOM tree until we find a <td>
while (cellNode.tagName != "TD")
cellNode = cellNode.parentNode;
// Collapse the currently open section if there is one
if (this._current != null)
this.dom(this._current).className = "desc";
if ("i" + index != this._current)
{
// Open the section we clicked on by changing its class
cellNode.className = "desc open";
cellNode.id = this.id + "-i" + index;
// Record this as the current one so we can close it later
this._current = "i" + index;
}
else
this._current = null;
// ???
zf_frame.recalcLayout();
return false;
};
Edit: added some comments
Unfortunately their code is in-lined and hard to read (http://www.zenfolio.com/zf/script/en-US/mozilla5/windows/5AN2EHZJSZSGS/sitehome.js), but this looks quite simple to implement... something along these lines (using prototypejs):
<script>
var showHide = {
cachedExpandable: null
,init: function() {
var containers = $$(".container");
for(var i=0, clickable; i<containers.length; i++) {
clickable = containers[i].getElementsByClassName("clickable")[0];
Event.observe(clickable, "click", function(e) {
Event.stop(e);
showHide.doIt(containers[i]);
});
}
}
,doIt: function(container) {
if(this.cachedExpandable) this.cachedExpandable.hide();
var expandable = container.getElementsByClassName("expandable")[0];
if(expandable.style.display == "none") {
expandable.show();
} else {
expandable.hide();
}
this.cachedExpandable = expandable;
}
};
window.onload = function() {
showHide.init();
};
</script>
<div class="container">
<div class="clickable">
Storage Space
</div>
<div class="expandable" style="display: none;">
Description for storage space
</div>
</div>
<div class="container">
<div class="clickable">
Galleries
</div>
<div class="expandable" style="display: none;">
Description for galleries
</div>
</div>
Its also caching the earlier expandable element, so it hides it when you click on a new one.

Categories

Resources