Dynamically assigning border radius to the li first-child in Javascript - javascript

I am trying to create a navigation bar with rounded corners for the first and last children (using an unordered list). I want to use the onclick javascript function and dynamically assign rounded corners within javascript. Here is my code which I tried. Can anyone please point me to the reason and/or suggest a solution or resource? Thanks a lot in advance.
HTML:
<nav>
<ul id="navBar">
<li><div class="menu" onClick="select(this)">View</div></li>
<li><div class="menu" onClick="select(this)">Duplicate</div></li>
<li><div class="menu" onClick="select(this)">Edit</div></li>
<li><div class="menu" onClick="select(this)">Delete</div></li>
</ul>
</nav>
Javascript:
document.getElementById('ul#navBar li:first-child').style.MozBorderRadiusTopleft = '13px';
document.getElementById('ul#navBar li:first-child').style.MozBorderRadiusBottomleft = '13px';
document.getElementById('ul#navBar li:last-child').style.MozBorderRadiusTopRight = '13px';
document.getElementById('ul#navBar li:last-child').style.MozBorderRadiusBottomRight = '13px';

CSS for your stylesheet:
.is-rounded li:first-child {
-moz-border-radius: 13px 0 0 13px;
-webkit-border-radius: 13px 0 0 13px;
border-radius: 13px 0 0 13px;
}
.is-rounded li:last-child {
-moz-border-radius: 0 13px 13px 0;
-webkit-border-radius: 0 13px 13px 0;
border-radius: 0 13px 13px 0;
}
Javascript:
function makeRounded(e) {
document.querySelector('#navBar').className += 'is-rounded';
}
document.querySelector('#el').addEventListener('click', makeRounded, false);
This assumes than an element with the id of "el" is the element that, when clicked, triggers the whole thing.
See example: http://jsfiddle.net/cgrFe/3/
You seem to know very little about this. A few books to get you started: http://domscripting.com/book/ and http://domenlightenment.com/ . The last of the two is fairly new, but must be good.

getElementById does not take a selector as its argument. Only a valid id of the element is required for its usage. You're probably thinking about jQuery:
$('ul#navBar li:first-child').css({
MozBorderRadiusTopleft: '13px'
});
$('navBar li:first-child').css({
MozBorderRadiusBottomleft: '13px'
});
$('ul#navBar li:last-child').css({
MozBorderRadiusTopRight: '13px'
});
$('navBar li:last-child').css({
MozBorderRadiusBottomRight: '13px'
});

I would make things really simple. Start by defining two css classes for rounded corners:
.round-top {
MozBorderRadiusTopleft:13px;
MozBorderRadiusTopRight:13px;
}
.round-bottom {
MozBorderRadiusBottomleft:13px;
MozBorderRadiusBottomRight:13px;
}
Then you can simply add/remove the class from the elements that you are interested in.
In javascript:
var container = document.getElementById(navBar);
container.firstChild.setAttribute("class", "round-top");
container.lastChild.serAttribute("class", "round-bottom");
Jquery:
$('#navBar li:first-child').addClass('round-top');
$('#navBar li:last-child').addClass('round-bottom');
A full event listener would be something like:
function addBorders(){
var container = document.getElementById(navBar);
container.firstChild.setAttribute("class", "round-top");
container.lastChild.serAttribute("class", "round-bottom");
}
//target is the element you want to trigger the event
target.addEventListener("click", addBorders, false);

If you can use jquery, you can do it in next way
intead "border", "3px double red" you should use your styles
<script type="text/javascript" language="javascript">
var Menu = {
rootEl: null,
Init: function (idRootEl) {
this.rootEl = $(idRootEl);
this.initItems();
this.setFirstElSeleceted();
},
setFirstElSeleceted: function () {
$($(this.rootEl).find('li')[0]).css("border", "3px double red");
},
initItems: function () {
var self = this;
$(self.rootEl).find('li').each(function (indx) {
$(this).click(function () {
self.removeSelection();
self.setSelected(this);
});
});
},
setSelected: function (el) {
$(el).css("border", "3px double red");
},
removeSelection: function () {
var self = this;
$(self.rootEl).find('li').each(function (el) {
$(this).css("border", "");
});
}
};
$(function() {
Menu.Init('ul#navBar');
});
</script>

Related

Dynamic <a> not clickable

I have done the following code in php so that I can click on the arrow and a form opens below
echo '<div class="editor" id="'.$par_code.'" style=" background-color: #fdfdfd; padding:14px 25px 30px 20px; font-family: Lucida Console, Monaco, monospace; box-shadow: 0 1px 10px 2px rgba(0,0,0,0.2),0 8px 20px 0 rgba(0,0,0,0.03); border-radius: 3px;">'
.'<img width="50" height="50" style="border-radius:50%" src="images/default.png" alt="Image cannot be displayed"/>'
.'<p class="uname"> '.$uname.'</p> '
.'<p class="time">'.$date.'</p>'
.'<p class="comment-text" style="word-break: break-all;">'.$content.'</p>'
.'<a class="link-reply al" id="reply" name="'.$par_code.'" style="padding-top: 18px; float: right;"><i class="fa fa-reply fa-lg" title="Reply"></i></a>';
My javascript code:
$(document).ready(function() {
$("a#reply").one("click" , function() {
var comCode = $(this).attr("name");
var parent = $(this).parent();
var str1 = "new-reply";
var str2 = "tog";
var res = str1.concat(i);
var tes = str2.concat(i);
// Create a new editor inside the <div id="editor">, setting its value to html
parent.append("<br /><center><form action='index.php' method='post' id='"+tes+"'><input class='iptext2' type='text' name='uname2' id='uname2' placeholder='Your Name' required /><div style='padding-bottom:5px'></div><textarea class='ckeditor' name='editor' placeholder='Your Query' id='"+res+"' required></textarea><input type='hidden' name='code' value='"+comCode+"' /><br/><input type='submit' class='form-submit' id='form-reply' name='new_reply' value='Reply' /></form></center>")
CKEDITOR.replace(res);
/*
var x = document.getElementById("tes");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
*/
i++;
});
})
The following is my css code applied to the anchor tag:
.al {
font-size:11.2px;
text-transform: uppercase;
text-decoration: none;
color:#222;
cursor:pointer;
transition:ease 0.3s all;
}
.al:hover {
color:#0072bc;
}
.link-reply {
color:#767676;
}
Here the arrow icon is displayed but is not clickable
Your code fails, because your <a> elements are created dynamically, whereas the event listener is added only to the elements available when the document has loaded.
In order to get your code to work, you need to use event delegation; that is to add the event listener to a common static ancestor, such as the document or the body, that will in turn delegate it to your target elements.
The methods you can use to achieve this effect in jQuery are on and one, with the latter fitting your case better, if you are trying to attach one-time event listeners.
Code:
$(document).one("click", "a#reply", function() {
// ...
});
Use on for dynamic created events on DOM.
$(document).on("click","a#reply" , function() {
console.log('a#reply => clicked!')
});
Or
$(body).on("click","a#reply" , function() {
console.log('a#reply => clicked!')
});

Tooltipster content doubling up each time it is opened

I'm using Tooltipster to show a list of items that the user can click so as to enter the item into a textarea. When a tooltip is created, I get its list of items with selectors = $("ul.alternates > li");
However, each time a tooltip is opened the item clicked will be inserted a corresponding number of times; for example if I've opened a tooltip 5 times then the item clicked will be inserted 5 times. I've tried deleting the variable's value after a tooltip is closed with functionAfter: function() {selectors = null;} but that had no effect.
I have a Codepen of the error here that should make it clearer.
// set list to be tooltipstered
$(".commands > li").tooltipster({
interactive: true,
theme: "tooltipster-light",
functionInit: function(instance, helper) {
var content = $(helper.origin).find(".tooltip_content").detach();
instance.content(content);
},
functionReady: function() {
selectors = $("ul.alternates > li");
$(selectors).click(function() {
var sampleData = $(this).text();
insertText(sampleData);
});
},
// this doesn't work
functionAfter: function() {
selectors = null;
}
});
// Begin inputting of clicked text into editor
function insertText(data) {
var cm = $(".CodeMirror")[0].CodeMirror;
var doc = cm.getDoc();
var cursor = doc.getCursor(); // gets the line number in the cursor position
var line = doc.getLine(cursor.line); // get the line contents
var pos = {
line: cursor.line
};
if (line.length === 0) {
// check if the line is empty
// add the data
doc.replaceRange(data, pos);
} else {
// add a new line and the data
doc.replaceRange("\n" + data, pos);
}
}
var code = $(".codemirror-area")[0];
var editor = CodeMirror.fromTextArea(code, {
mode: "simplemode",
lineNumbers: true,
theme: "material",
scrollbarStyle: "simple",
extraKeys: { "Ctrl-Space": "autocomplete" }
});
body {
margin: 1em auto;
font-size: 16px;
}
.commands {
display: inline-block;
}
.tooltip {
position: relative;
opacity: 1;
color: inherit;
}
.alternates {
display: inline;
margin: 5px 10px;
padding-left: 0;
}
.tooltipster-content .alternates {
li {
list-style: none;
pointer-events: all;
padding: 15px 0;
cursor: pointer;
color: #333;
border-bottom: 1px solid #d3d3d3;
span {
font-weight: 600;
}
&:last-of-type {
border-bottom: none;
}
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.2/theme/material.min.css" rel="stylesheet"/>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/235651/jquery-3.2.1.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/235651/tooltipster.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.2/codemirror.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.2/addon/mode/simple.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.2/addon/hint/show-hint.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.2/addon/scroll/simplescrollbars.js"></script>
<div class="container">
<div class="row">
<div class="col-md-6">
<ul class="commands">
<li><span class="command">Hover for my list</span><div class="tooltip_content">
<ul class="alternates">
<li>Lorep item</li>
<li>Ipsum item</li>
<li>Dollar item</li>
</ul>
</li>
</div>
</ul>
</div>
<div class="col-md-6">
<textarea class="codemirror-area"></textarea>
</div>
</div>
</div>
Tooltipster's functionReady fires every time the tooltip is added to the DOM, which means every time a user hovers over the list, you are binding the event again.
Here are two ways to prevent this from happening:
Attach a click handler to anything that exists in the DOM before the tooltip is displayed. (Put it outside of tooltipspter(). No need to use functionReady.)
Example:
$(document).on('click','ul.alternates li', function(){
var sampleText = $(this).text();
insertText(sampleText);
})
Here's a Codepen.
Unbind and bind the event each time functionReady is triggered.
Example:
functionReady: function() {
selectors = $("ul.alternates > li");
$(selectors).off('click').on('click', function() {
var sampleData = $(this).text();
insertText(sampleData);
});
}
Here's a Codpen.
You are binding new clicks every time.
I would suggest different code style but in that format you can just add before the click event
$(selectors).unbind('click');
Then do the click again..

Change styling of div when a click out of the div is detected

I have 8 divs in Bootstrap and I can change the styling of a div when I click on it with the following code;
$(document).ready(function() {
$(".continue--btn").hide();
if ($('.generator--templates').click(function(){
$('.continue--btn').show();
$(this).css("background", "#03A9F3");
$(this).find('.generator--templates__description, .generator--templates__purpose').css("color", "#fff");
})
);
This also shows a button to continue.
However, the next thing I want to do is when I click anywhere but the div, div gets his default styling and that the button will disappear again.
I can not wrap my head around this.
I've tried this:
var templates = document.getElementsByClassName('.generator--templates');
window.onclick = function(event){
if (event.target == templates){
templates.style.background = "#fff";
}
}
Firstly note that your syntax is incorrect in that you have placed a click() handler in an if statement.
Secondly, templates will be a collection of elements returned from getElementsByClassName. Therefore comparing it to the Element in event.target is never going to match.
To fix the issue put a click handler on the document and check the class of the target element, something like this:
$(document).ready(function() {
$('.generator--templates').click(function() {
$('.continue--btn').show();
$(this).find('.generator--templates__description, .generator--templates__purpose').addBack().addClass('active');
})
$(document).on('click', function(e) {
var $target = $(this);
if ($target.is('.generator--templates') || $target.closest('.generator--templates').length) {
$('.continue--btn').hide();
$('.generator--templates').removeClass('active');
}
});
});
.continue--btn {
display: none;
}
.generator--templates.active,
.generator--templates__description.active,
.generator--templates__purpose.active {
color: #FFF;
}
Note the use of CSS here instead of css() which should be avoided where possible, as it ties the JS logic too closely to the UI.
Please try this:
$(".continue--btn").hide();
$('.generator--templates').click(function() {
// reset the sibling elements
$(this).siblings('.generator--templates').each(function(i, el) {
$(el).find('.continue--btn').hide();
$(el).css('background', 'rgba(0, 0, 0, 0.2)');
$(el).find('.generator--templates__description, .generator--templates__purpose').css("color", "transparent");
});
// apply changes to clicked item
$(this).find('.continue--btn').show();
$(this).css("background", "#03A9F3");
$(this).find('.generator--templates__description, .generator--templates__purpose').css("color", "#fff");
});
$('.body').click(function(e) { // change '.body' to 'body' for your code
var $target = jQuery(e.target);
if ($target.hasClass('generator--templates') ||
$target.closest('.generator--templates').length > 0) {
// Clicked on a box
} else { // Clicked elsewhere
$('.generator--templates').each(function(i, el) {
$(el).find('.continue--btn').hide();
$(el).css('background', 'rgba(0, 0, 0, 0.2)');
$(el).find('.generator--templates__description, .generator--templates__purpose').css("color", "transparent");
});
}
});
.body {
/* added just for display */
background: rgba(0, 0, 0, 0.1);
width: 100%;
height: 500px
}
.generator--templates {
background-color: rgba(0, 0, 0, 0.2);
width: 150px;
height: 150px;
float: left;
margin-right: 10px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1) inset
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="body">
<div class="container-element">
<div class="generator--templates one">
<button class="continue--btn">Continue</button>
</div>
<div class="generator--templates two">
<button class="continue--btn">Continue</button>
</div>
<div class="generator--templates three">
<button class="continue--btn">Continue</button>
</div>
</div>
</div>

HTML append a class based on the name of current class JS

Is there a way to append a class to the current class name?
<li class="myWrap"></li>
Then onClick toggle class:
$('.myWrap').toggleClass('selected');
Is there anyway I can read the current class i've select and appended it to my one i'm adding. So my new class instead of:
<section class="myWrap selected"></section>
It will be:
<section class="myWrap myWrap_selected"></section>
.toggleClass() can already do this for you but you will need a way to determine the base class, because at any given point your elements can have more than one class (the base class, the selected class and any others). If you ensure that your base class will remain the first specified, then you can use the following.
$('li').on('click', function() {
// find the base class
var baseClass = $(this).attr('class').split(' ')[0];
// toggle the selected class
$(this).toggleClass(baseClass + '_selected');
});
$(function() {
$('li').on('click', function() {
var baseClass = $(this).attr('class').split(' ')[0];
$(this).toggleClass(baseClass + '_selected');
});
});
li.myClass {
border: 1px dashed red;
background-color: #ffcccc;
}
li.myClass_selected {
border-style:solid;
}
li.myWrap {
border: 1px dashed green;
background-color: #ccffcc;
}
li.myWrap_selected {
border-style:solid;
}
li.otherClass {
font-style:italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="myClass otherClass">Hello class</li>
<li class="myWrap otherClass">Hello wrap</li>
</ul>
Please try this function:
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$('.myWrap').on('click', function() {
var newclass = $(this).attr('class') + "_selected";
$(this).toggleClass(newclass);
});
});
</script>

How to convert unordered list into nicely styled <select> dropdown using jquery?

How do I convert an unordered list in this format
<ul class="selectdropdown">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
<li>seven</li>
</ul>
into a dropdown in this format
<select>
<option value="one.html" target="_blank">one</option>
<option value="two.html" target="_blank">two</option>
<option value="three.html" target="_blank">three</option>
<option value="four.html" target="_blank">four</option>
<option value="five.html" target="_blank">five</option>
<option value="six.html" target="_blank">six</option>
<option value="seven.html" target="_blank">seven</option>
</select>
using jQuery?
Edit: When selecting an entry from the select/dropdown the link should open in a new window or tab automatically. I also want to able to style it like: http://www.dfc-e.com/metiers/multimedia/opensource/jqtransform/
$(function() {
$('ul.selectdropdown').each(function() {
var $select = $('<select />');
$(this).find('a').each(function() {
var $option = $('<option />');
$option.attr('value', $(this).attr('href')).html($(this).html());
$select.append($option);
});
$(this).replaceWith($select);
});
});
EDIT
As with any jQuery code you want to run on page load, you have to wrap it inside $(document).ready(function() { ... }); block, or inside it's shorter version $(function() { ... });. I updated the function to show this.
EDIT
There was a bug in my code also, tried to take href from the li element.
$('ul.selectdropdown').each(function() {
var select = $(document.createElement('select')).insertBefore($(this).hide());
$('>li a', this).each(function() {
var a = $(this).click(function() {
if ($(this).attr('target')==='_blank') {
window.open(this.href);
}
else {
window.location.href = this.href;
}
}),
option = $(document.createElement('option')).appendTo(select).val(this.href).html($(this).html()).click(function() {
a.click();
});
});
});
In reply to your last comment, I modified it a little bit but haven't tested it. Let me know.
$('ul.selectdropdown').each(function() {
var list = $(this), select = $(document.createElement('select')).insertBefore($(this).hide());
$('>li a', this).each(function() {
var target = $(this).attr('target'),
option = $(document.createElement('option'))
.appendTo(select)
.val(this.href)
.html($(this).html())
.click(function(){
if(target==='_blank') {
window.open($(this).val());
}
else {
window.location.href = $(this).val();
}
});
});
list.remove();
});
This solution is working also in IE and working with selected item (in anchor tag).
$('ul.selectdropdown').each(function(){
var list=$(this),
select=$(document.createElement('select')).insertBefore($(this).hide()).change(function(){
window.location.href=$(this).val();
});
$('>li a', this).each(function(){
var option=$(document.createElement('option'))
.appendTo(select)
.val(this.href)
.html($(this).html());
if($(this).attr('class') === 'selected'){
option.attr('selected','selected');
}
});
list.remove();
});
Thank you all for posting the codes. My scenario is similar but my situation is for Responsiveness that for x-size it would switch to a dropdown list, then if not x-size, using csswatch to check for the "display" properties of an element that has certain amount of width set to it (eg: 740px). Thought I share this solution for anyone who is interested. This is what I have combined with Tatu' codes. Instead of replacing the html, I created then hide the new html then only add them when necessary:
var $list = $('ul.list');
(listFunc = function(display){
//Less than x-size turns it into a dropdown list
if(display == 'block'){
$list.hide();
if($('.sels').length){
$('.sels').show();
} else {
var $select = $('<select class="sels" />');
$list.find('a').each(function() {
var $option = $('<option />');
$option.attr('value', $(this).attr('href')).html($(this).html());
$select.append($option);
});
$select.insertAfter($list);
$('.sels').on('change', function(){
window.location = this.value;
});
}
} else {
$('.sels').hide();
$list.show();
}
})(element.css('display'));
element.csswatch({
props: 'display'
}).on('css-change', function (event, change) {
return listFunc(change.display);
});
I have recently created a solution where the ul transformed, mimics nearly completely the select.
It has in adition a search for the options of the select and supports the active state. Just add a class with name active and that option will be selected.
It handles the keyboard navigation.
Take a look at the code here: GitHub Code
And a live example here: Code Example
The unordered list must be in the form:
<ul id="...">
<li>...</li>
<li>...</li>
<li><a class="active" href="...">...</a></li>
...
</ul>
To convert the ul to select just call:
$(window).on("load resize", function() {
ulToSelect($("ul#id"), 767);
});
Where #id is an id for the unordered list and 767 is the minimum width of the window for the convertion to take place. This is very useful if you want the convertion to take place only for mobile or tablet.
I found this gorgeous CodePen from #nuckecy for anyone interested:
https://codepen.io/nuckecy/pen/ErPqQm
$(".select").click(function() {
var is_open = $(this).hasClass("open");
if (is_open) {
$(this).removeClass("open");
} else {
$(this).addClass("open");
}
});
$(".select li").click(function() {
var selected_value = $(this).html();
var first_li = $(".select li:first-child").html();
$(".select li:first-child").html(selected_value);
$(this).html(first_li);
});
$(document).mouseup(function(event) {
var target = event.target;
var select = $(".select");
if (!select.is(target) && select.has(target).length === 0) {
select.removeClass("open");
}
});
His default CSS rules:
.select li {
display: none;
cursor: pointer;
padding: 5px 10px;
border-top: 1px solid black;
min-width: 150px;
}
.select li:first-child {
display: block;
border-top: 0px;
}
.select {
border: 1px solid black;
display: inline-block;
padding: 0;
border-radius: 4px;
position: relative;
}
.select li:hover {
background-color: #ddd;
}
.select li:first-child:hover {
background-color: transparent;
}
.select.open li {
display: block;
}
.select span:before {
position: absolute;
top: 5px;
right: 15px;
content: "\2193";
}
.select.open span:before {
content: "\2191";
}

Categories