I use jqtouch and have a checkbox:
<li>Checkbox1<span class="toggle"><input type="checkbox" id="1" onclick="Javascript:SetGPIO('1')"> </span></li>
I can enable this checkbox:
$('#1').prop('checked', true);
or
$('#1').attr('checked', true);
and i can disable
$('#1').removeAttr("checked");
This works well.
However, once the user has switched the checkbox, the checkbox can not set by the code above.
I have also tried with:
$('#1').prop("checked",false); //Enables the checkbox (?)
$('#1').attr('checked', false); //enables the checkbox (?)
What can i do, to set the checkbox via JavaScript, after the user has pressed the checkbox?
[Edit]
I have here a complete example for jqtouch:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>jQTouch β</title>
<link rel="stylesheet" href="../../themes/css/jqtouch.css"
title="jQTouch">
<script src="../../src/lib/zepto.min.js" type="text/javascript"
charset="utf-8"></script>
<script src="../../src/jqtouch.min.js" type="text/javascript"
charset="utf-8"></script>
<!-- Uncomment the following two lines (and comment out the previous two) to use jQuery instead of Zepto. -->
<!-- <script src="../../src/lib/jquery-1.7.min.js" type="application/x-javascript" charset="utf-8"></script> -->
<!-- <script src="../../src/jqtouch-jquery.min.js" type="application/x-javascript" charset="utf-8"></script> -->
<script src="../../extensions/jqt.themeswitcher.min.js"
type="application/x-javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var jQT = new $.jQTouch({
icon : 'jqtouch.png',
icon4 : 'jqtouch4.png',
addGlossToIcon : false,
startupScreen : 'jqt_startup.png',
statusBar : 'black-translucent',
themeSelectionSelector : '#jqt #themes ul',
preloadImages : []
});
// Some sample Javascript functions:
$(function() {
// Show a swipe event on swipe test
$('#swipeme').swipe(
function(evt, data) {
var details = !data ? '' : '<strong>' + data .direction
+ '/' + data.deltaX + ':' + data.deltaY
+ '</strong>!';
$(this).html('You swiped ' + details);
$(this).parent().after('<li>swiped!</li>')
});
$('#tapme').tap(function() {
$(this).parent().after('<li>tapped!</li>')
});
$('a[target="_blank"]').bind('click', function() {
if (confirm('This link opens in a new window.')) {
return true;
} else {
return false;
}
});
// Page animation callback events
$('#pageevents').bind(
'pageAnimationStart',
function(e, info) {
$(this).find('.info').append(
'Started animating ' + info.direction
+ '… And the link '
+ 'had this custom data: '
+ $(this).data('referrer').data('custom')
+ '<br>');
}).bind(
'pageAnimationEnd',
function(e, info) {
$(this).find('.info').append(
'Finished animating ' + info.direction
+ '.<br><br>');
});
// Page animations end with AJAX callback event, example 1 (load remote HTML only first time)
$('#callback').bind(
'pageAnimationEnd',
function(e, info) {
// Make sure the data hasn't already been loaded (we'll set 'loaded' to true a couple lines further down)
if (!$(this).data('loaded')) {
// Append a placeholder in case the remote HTML takes its sweet time making it back
// Then, overwrite the "Loading" placeholder text with the remote HTML
$(this).append(
$('<div>Loading</div>').load(
'ajax.html .info',
function() {
// Set the 'loaded' var to true so we know not to reload
// the HTML next time the #callback div animation ends
$(this).parent().data('loaded',
true);
}));
}
});
// Orientation callback event
$('#jqt').bind('turn', function(e, data) {
$('#orient').html('Orientation: ' + data.orientation);
});
});
function toggleCheckbox(){
if ($('#myCheckbox1').attr('checked') == 'true'){
$('#myCheckbox1').removeAttr("checked");
}
else {
$('#myCheckbox1').attr('checked', true);
}
window.setTimeout('toggleCheckbox()', 2000); //toggle every 2 seconds
}
toggleCheckbox();
</script>
<style type="text/css" media="screen">
#jqt.fullscreen #home .info {
display: none;
}
div#jqt #about {
padding: 100px 10px 40px;
text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0;
color: #999;
font-size: 13px;
text-align: center;
background: #161618;
}
div#jqt #about p {
margin-bottom: 8px;
}
div#jqt #about a {
color: #fff;
font-weight: bold;
text-decoration: none;
}
</style>
</head>
<body>
<div id="jqt">
<div id="home" class="current">
<div class="scroll">
<ul class="rounded">
<li>MyCheckbox<span class="toggle"><input
type="checkbox" id="myCheckbox1" >
</span>
</li>
</ul>
</div>
</div>
</div>
</body>
The checkbox toggle every 2 seconds, but only until the user clicks on this.
I hope now my question is a little clearer. And sorry for my bad english.
[/edit]
First, what you're actually doing is checking and unchecking the boxes as opposed to enabling and disabling them (disabled means the user can't check or uncheck the box anymore). Second, the checked property isn't set to true/false (though that would make more sense) you have to set checked to "checked" to have it checked and remove the property to uncheck it.
$('#1').attr('checked', 'checked'); //Check
$('#1').removeAttr("checked"); //Uncheck
Related
Okay, basically what I want to try to achieve, is when a dragover event fires from HTML5 Drag And Drop API, I wish to create a jQuery draggable object, and start following the mouse around, while the dragend event fires from the HTML5 Drag And Drop API.
The reason I want to do this, is the following:
I have an application which uses a plugin, that has a functionality, which is dependent on the jQuery.ui draggable to function (it is the FullCalendar Scheduler plugin, version 3)
I want to achieve a new functionality in the application, with which the client can drag something from browser window A, and drop it in the above mentioned plugin in browser window B.
As the above mentioned plugin is not working with the native HTML5 Drag and Drop API, and the jQuery.ui draggable is not capable of dragging elements from one browser window to the other, I think my only option is to mix these two plugins.
My proposed solution to this problem was, using the native HTML5 Drag and Drop API, and when the dragged element reaches over a dropzone, creating a new draggable element in browser window B, and simulating a mousedown event on it, so it starts following the cursor. When the dragend event would fire, I planned to plain and simply fire the mouseup event on the draggable element also, and from here on the scheduler plugin can do it's magic.
To try to test this out, with a single browser window at first, I've tried to achieve the first part of my above solution, ie: when the dragover fires, create the jQuery.ui draggable and simulate a mousedown on it, then it should start following the mouse. I can't achieve this behaviour.
I made a fiddle, where you can see what I tried so far (I am not posting the whole code here, as it is rather long): JSFiddle
Basically, the error I am getting at the Fiddle, with both options that I tried, is a type.indexOf is not a function error.
I also asked and received some help on the following question, from where the proposed solution works fine when starting the drag operation with a click event, but it isn't working with any other event type. I pressume, I can simulate a mousedown.draggable event, only from a MouseEvent, and the dragend event is not a MouseEvent.
Long story short, I would need help in obtaining the result I am looking for, at least for the first part of my proposed solution!
There does not appear to be a good answer for this. First, not all browsers support the same DnD terminology or functionality. Such as FireFox fires a dragenter event on drop and Chrome does not seem to detect a drop event when the object is from another window.
Here is my testing so far. To use, copy the content into a Text file and save as HTM or HTML. Then Open the file locally in your browser. Open another Window and open the second HTM. now you have two windows you can drag to and from.
wina-1.htm
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Window A</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
.items {
position: relative;
}
.items > div {
margin-right: 5px;
width: 150px;
height: 150px;
padding: 0.5em;
border-radius: 6px;
display: inline-block;
}
#log {
width: 100%;
height: 5em;
overflow-y: auto;
}
[draggable].idle {
background-color: rgba(255,0,0,0.75);
}
[draggable].selected {
background-color: rgba(255,0,0,0.95);
}
</style>
</head>
<body>
<pre id="log"></pre>
<div class="items ui-widget">
<div id="draggable" class="ui-widget-content idle" draggable="true">
<p>Drag me around</p>
</div>
<div id="static" class="ui-widget-content">
<p>I can't be moved</p>
</div>
</div>
<script>
var srcEl;
function log(s){
var now = new Date();
var t = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds()
+ "." + now.getMilliseconds();
var l = document.getElementById("log");
l.append(t + ": " + s + "\r\n");
l.scrollTop = l.scrollHeight;
}
function dragStart(e){
log("Drag Start: " + e.target.nodeName + "#" + e.target.id);
srcEl = e.target;
if(e.dataTransfer == undefined){} else {
e.dataTransfer.effectAllowed = "copyMove";
log("Event dataTransfer.effectAllowed: " +
e.dataTransfer.effectAllowed);
log("Source Element: " + srcEl.nodeName + "#" + srcEl.id);
}
this.classList.add("selected");
}
function dragOver(e){
e.preventDefault();
log("Drag Over: " + e.target.nodeName + (e.target.id != "" ? "#" +
e.target.id : ""));
return false;
}
function dragLeave(e){
log("Drag Leave: " + e.target.nodeName + (e.target.id != "" ? "#" +
e.target.id : ""));
}
function dragStop(e){
log("Drag End: " + e.target.nodeName + "#" + e.target.id);
this.classList.remove("selected");
}
log("Init");
var item = document.getElementById("draggable");
item.addEventListener('dragstart', dragStart, false);
item.addEventListener('dragover', dragOver, false);
item.addEventListener('dragleave', dragLeave, false);
window.addEventListener('dragleave', dragLeave, false);
var items = document.querySelectorAll('.items > div');
[].forEach.call(items, function(el) {
el.addEventListener('dragover', dragOver, false);
});
</script>
</body>
</html>
As you can see, this is using raw JavaScript. I was tinkering with jQuery UI, and I kept the stylesheet just for easy theming. We have a section to print out log details, a draggable, and a static item.
winb-1.htm
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Window B</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
.drag-item {
width: 100px;
height: 100px;
background-color: red;
}
body {
position: relative;
}
div.drag-helper {
width: 100px;
height: 100px;
background-color: red;
z-index: 1002;
position: relative;
}
#log {
width: 100%;
height: 5em;
line-height: 1em;
font-size: 1em;
overflow-y: auto;
}
#dropzone {
background-color: green;
width: 95%;
height: 340px;
}
</style>
</head>
<body>
<pre id="log"></pre>
<div id="dropzone"></div>
<script>
jQuery(function($) {
function log(s){
var now = new Date();
var t = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds
() + "." + now.getMilliseconds();
$("#log").append(t + ": " + s + "\r\n").scrollTop($("#log").prop
("scrollHeight"));
}
function dragEnter(e){
e.preventDefault();
log("Drag Enter triggered: " + $(e.target).prop("nodeName") +
($(e.target).attr("id").length ? "#" + $(e.target).attr("id") : ""));
}
function dragOver(e){
log("Drag Over triggered: " + $(e.target).prop("nodeName") +
($(e.target).attr("id").length ? "#" + $(e.target).attr("id") : ""));
e.dataTransfer.dropEffect = 'move';
e.preventDefault();
}
function handleDrop(e){
if (e.stopPropagation) {
e.stopPropagation();
}
log("Drop Triggered: " + $(e.target).attr("id"));
return false;
}
function dragEnd(e){
log("Drag End Triggered: " + $(e.target).prop("nodeName") +
($(e.target).attr("id").length ? "#" + $(e.target).attr("id") : ""));
}
log("Init");
$("#dropzone").on({
dragenter: dragEnter,
dragover: dragOver,
drop: handleDrop,
mouseup: handleDrop,
dragend: dragEnd
});
$(window).on({
dragenter: dragEnter,
dragover: dragOver,
drop: handleDrop,
dragend: dragEnd
});
});
</script>
</body>
</html>
Window B uses jQuery as the intention was to convert the element into a jQuery UI Draggable.
First thing to know, there is no way to do in transit. Since the Source element is not a part of the target DOM, it cannot be done. It can be added and initialized as a Draggable in the drop event. Essentially what will happen is a new element will be created at that time assigned all the data.
Second, data transfer is unreliable and I would avoid DataTransfer as your data container. I would advise using localStorage. This is similar to a cookie and is a lot more reliable.
For example, I created the following Data object:
{
id,
type,
attr: {
id,
class,
width,
height
},
content
}
Here are some example functions:
function collectData(obj){
return {
id: obj.attr("id"),
type: obj.prop("nodeName"),
attr: {
id: obj.attr("id"),
class: obj.attr("class"),
width: obj.width(),
height: obj.height()
},
content: obj.text().trim()
};
}
function saveData(k, d){
localStorage.setItem(k, JSON.stringify(d));
}
function getData(k){
return JSON.parse(localStorage.getItem(k));
}
function makeEl(d, pObj){
return $("<" + d.type +">", d.attr).html("<p>" + d.content + "</p>").appendTo(pObj);
}
$("#draggable").on('dragstart', function(e){
saveData("drag-data", collectData($(this)));
});
$("#dropzone").on('drop', function(e){
var item = makeEl(getData('drag-data'), $(this));
item.addClass("clone").position({
my: "center",
of: e
}).draggable();
});
In theory, this should all work. In practice, I have hit a ton of roadblocks. I would suggest something like a click-to-copy type of action. Where the User clicks an item in Window A (selecting it) and then clicks where they want it to be in Window B. Again using localStorage, the item could be cloned into the new location.
wina-3.htm
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
.items {
position: relative;
}
.items > div {
margin-right: 5px;
width: 150px;
height: 150px;
padding: 0.5em;
border-radius: 6px;
display: inline-block;
}
#log {
width: 100%;
height: 5em;
overflow-y: auto;
}
[draggable].idle {
background-color: rgba(255,0,0,0.5);
}
[draggable].selected {
background-color: rgba(255,0,0,0.95);
}
</style>
</head>
<body>
<pre id="log"></pre>
<div class="items ui-widget">
<div id="draggable" class="ui-widget-content idle" draggable="true">
<p>Click on me</p>
</div>
<div id="static" class="ui-widget-content">
<p>I can't be moved</p>
</div>
</div>
<script>
var intv;
function log(s){
var now = new Date();
var t = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds() + "." + now.getMilliseconds();
var l = document.getElementById("log");
l.append(t + ": " + s + "\r\n");
l.scrollTop = l.scrollHeight;
}
function collectData(el){
return {
id: el.id,
type: el.nodeName,
attr: {
id: el.id,
class: el.className,
width: el.width,
height: el.height
},
content: el.innerText
};
}
function saveData(k, v){
localStorage.setItem(k, JSON.stringify(v));
}
function getData(k){
return JSON.parse(localStorage.getItem(k));
}
function clearData(k){
localStorage.setItem(k, null);
}
function selElem(e){
var trg = e.target.nodeName + (e.target.id != "" ? "#" + e.target.id : "");
if(e.target.classList.contains("selected")){
log("Deselect element: " + trg);
e.target.classList.remove("selected");
} else {
log("Element Selected: " + trg);
e.target.classList.add("selected");
saveData("select-data", collectData(e.target));
}
intv = setInterval(function(){
if(getData("select-data") == null){
document.getElementsByClassName("selected")[0].classList.remove("selected");
log("Unselected");
clearInterval(intv);
}
}, 1000);
}
log("Init");
var item = document.getElementById("draggable");
item.addEventListener('click', selElem);
</script>
</body>
</html>
winb-3.htm
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Window B</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
.drag-item {
width: 100px;
height: 100px;
background-color: red;
}
body {
position: relative;
}
#log {
width: 100%;
height: 5em;
line-height: 1em;
font-size: 1em;
overflow-y: auto;
}
#dropzone {
background-color: green;
width: 95%;
height: 340px;
position: relative;
}
.cloned {
position: absolute;
width: 150px;
height: 150px;
padding: 0.5em;
border-radius: 6px;
display: inline-block;
background-color: rgba(255,0,0,0.75);
}
</style>
</head>
<body>
<pre id="log"></pre>
<div id="dropzone"></div>
<script>
jQuery(function($) {
function log(s){
var now = new Date();
var t = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds
() + "." + now.getMilliseconds();
$("#log").append(t + ": " + s + "\r\n").scrollTop($("#log").prop
("scrollHeight"));
}
function getData(k){
console.log("Getting Data: '" + k + "'", localStorage.getItem(k));
return JSON.parse(localStorage.getItem(k));
}
function clearData(k){
log("Clear Data");
localStorage.setItem(k, null);
}
function makeEl(dObj, pObj){
console.log(dObj, pObj);
return $("<" + dObj.type + ">", dObj.attr).html("<p>" + dObj.content +
"</p>").appendTo(pObj);
}
function handleDrop(e){
if (e.stopPropagation) {
e.stopPropagation();
}
var trg = $(e.target);
log("Drop Triggered: " + trg.prop("nodeName") + "#" + trg.attr("id"));
var d, item;
if(e.target.id == "dropzone" && (e.type == "click" || e.type ==
"mouseup")){
log("Click Detected - Collecting Data");
d = getData("select-data");
console.log("Data", d);
d.attr.id = "clone-" + ($("#dropzone .cloned").length + 1);
log("Making Element: " + d.type + "#" + d.attr.id);
item = makeEl(d, trg);
item.removeClass("selected").addClass("cloned").position({
my: "center",
of: e
}).draggable();
clearData("select-data");
return true;
}
return false;
}
log("Init");
$("#dropzone").on({
mouseup: handleDrop,
click: handleDrop
});
});
</script>
</body>
</html>
I know this is not the answer you're looking for, and for that you need to try to ask the real question. You seem to keep asking around the question.
Hope this helps.
I'm building a web app in which the user can type in any key word or statement and get in return twenty results from wikipedia using the wikipedia API. AJAX works just fine. When the web app pulls data from wikipedia it should display each result in a DIV created dynamically.
What happens is that, when the click event is fired, the twenty DIVs are created five times, so one hundred in total. I don't know why but, as you can see in the snippet below, the web app creates twenty DIVs for each DOM element that has been hidden (through .hide) when the click event is fired.
Here's is the code:
function main() {
function positive() {
var bar = document.getElementById("sb").childNodes[1];
var value = bar.value;
if (!value) {
window.alert("Type in anything to start the research");
} else {
var ex = /\s+/g;
var space_count = value.match(ex);
if (space_count == null) {
var new_text = value;
} else {
new_text = value.replace(ex, "%20");
//console.log(new_text);
}
url = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=&list=search&continue=-%7C%7C&srsearch=" + new_text + "&srlimit=20&sroffset=20&srprop=snippet&origin=*";
var request = new XMLHttpRequest();
request.open("GET", url);
//request.setRequestHeader("Api-User-Agent", "Example/1.0");
request.onload = function() {
var data = JSON.parse(request.responseText);
render(data);
//console.log(data);
}
request.send();
}
}
function render(data) {
$("#first_h1, #first_h3, #sb label, #second_h1, #second_h3").hide("slow", function() {
$("#sb input").css({
"float":"left",
"margin-left":"130px"
});
$("#first_btn").css({
"float":"left"
});
var title = data.query.search[0].title;
var new_text = document.createTextNode(title);
var new_window = document.createElement("div");
new_window.appendChild(new_text);
new_window.setAttribute("class", "window");
var position = document.getElementsByTagName("body")[0];
position.appendChild(new_window);
//}
});
}
var first_btn = document.getElementById("first_btn");
first_btn.addEventListener("click", positive, false);
}
$(document).ready(main);
html {
font-size: 16px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;ù
}
.align {
text-align: center;
}
#first_h1 {
margin-top: 30px;
}
#first_h3 {
margin-bottom: 30px;
}
#sb {
margin-bottom: 10px;
}
#second_h1 {
margin-top: 30px;
}
#second_h3 {
margin-bottom: 30px;
}
.window {
width: 70%;
height: 150px;
border: 3px solid black;
margin: 0 auto;
margin-top: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Wikipedia Viewer</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<h1 class="align" id="first_h1">Wikipedia Viewer</h1>
<h3 class="align" id="first_h3">Type in a key word about the topic you are after<br>and see what Wkipedia has for you..</h3>
<p class="align" id="sb">
<input type="text" name="search_box" placeholder="Write here">
<label for="search_box">Your search starts here...</label>
</p>
<p class="align" id="first_btn">
<input type="submit" value="SEND">
</p>
<h1 class="align" id="second_h1">...Or...</h1>
<h3 class="align" id="second_h3">If you just feel eager of random knowledge,<br>punch the button below and see what's next for you...</h3>
<p class="align" id="second_btn">
<input type="submit" value="Enjoy!">
</p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery-3.2.1.min.js"><\/script>')
</script>
<script type="text/javascript" src="js/script.js"></script>
</body>
</html>
I made the code easier to read by erasing the for loop. As you can see, even with just one result, it is displayed five times.
Do you know guys why it happens?
thanks
The line:
$("#first_h1, #first_h3, #sb label, #second_h1, #second_h3").hide("slow", function() {})
Says, for every element in this "list", hide the element and run this block of code after hidden.
This code is the culprit:
$("#first_h1, #first_h3, #sb label, #second_h1, #second_h3").hide("slow",
function() {...});
The callback function is called five times, one for each ID listed, not once for all of them, as you might expect.
A workaround is to create a class (say, "hideme"), apply it to each element you want to hide, and write:
$('.hideme').hide("slow", function() {...});
function render(data) {
$("#first_h1, #first_h3, #sb label, #second_h1, #second_h3").hide("slow", function() {
$("#sb input").css({
"float":"left",
"margin-left":"130px"
});
$("#first_btn").css({
"float":"left"
});
}); // Finish it here..
var title = data.query.search[0].title;
var new_text = document.createTextNode(title);
var new_window = document.createElement("div");
new_window.appendChild(new_text);
new_window.setAttribute("class", "window");
var position = document.getElementsByTagName("body")[0];
position.appendChild(new_window);
//}
// }); Move this line..
}
As described in the docs:
complete: A function to call once the animation is complete, called once per matched element.
Which means this line will call the handle function 5 times with 5 matched elements.
$("#first_h1, #first_h3, #sb label, #second_h1, #second_h3").hide("slow", function() {
The easiest solution is moving the render codes outside of the hide event handler
In my project I need to keep notification open unless user clicks on it and if there is an update in the time between it was triggerred and the user clicks on it, i need to update the value on the toast notificaiton.
I don't find any reference on how can i update a notification. Does anyone know ?
i'm using this github repo : toastr.js
please suggest
You can keep the toast open indefinitely by setting a timeOut value of 0 on the global scope using toast.options.
Alternately, you can set it using the third argument of the toast method.
For example:
toastr.success("message body", "title", {timeOut:0})
For your second question, you can update an existing toast by capturing it's reference when it's created, and then mutating it after creation.
For example:
var myToast = toastr.success("message body", "title", {timeOut:0});
myToast.find(".toast-title").text("new title");
myToast.find(".toast-message").text("new message");
You may also want to set the extendedTimeOut to 0 too, in case the user hovers over the toast before you've finished with it, like so:
var myToast = toastr.success("message body", "title", {timeOut:0, extendedTimeOut:0});
Then when you're done you can hide the toast programmatically:
$(myToast).fadeOut();
I assume you have a unique id for each toast. This will do the job:
var t = toastr.warning("message", "title");
t.attr('id', 'your unique id');
Afterwards you can select each toastr simply like this:
t = $('#id')
There is a easy solution like this-
toastr.options.timeOut = 0;
Demo Code-
$(function() {
function Toast(type, css, msg) {
this.type = type;
this.css = css;
this.msg = 'This is positioned in the ' + msg + '. You can also style the icon any way you like.';
}
var toasts = [
new Toast('error', 'toast-bottom-full-width', 'This is positioned in the bottom full width. You can also style the icon any way you like.'),
new Toast('info', 'toast-top-full-width', 'top full width'),
new Toast('warning', 'toast-top-left', 'This is positioned in the top left. You can also style the icon any way you like.'),
new Toast('success', 'toast-top-right', 'top right'),
new Toast('warning', 'toast-bottom-right', 'bottom right'),
new Toast('error', 'toast-bottom-left', 'bottom left')
];
toastr.options.positionClass = 'toast-top-full-width';
toastr.options.extendedTimeOut = 0; //1000;
toastr.options.timeOut = 0;
toastr.options.fadeOut = 250;
toastr.options.fadeIn = 250;
var i = 0;
$('#tryMe').click(function () {
$('#tryMe').prop('disabled', true);
delayToasts();
});
function delayToasts() {
if (i === toasts.length) { return; }
var delay = i === 0 ? 0 : 2100;
window.setTimeout(function () { showToast(); }, delay);
// re-enable the button
if (i === toasts.length-1) {
window.setTimeout(function () {
$('#tryMe').prop('disabled', false);
i = 0;
}, delay + 1000);
}
}
function showToast() {
var t = toasts[i];
toastr.options.positionClass = t.css;
toastr[t.type](t.msg);
i++;
delayToasts();
}
})
body {
margin: 5em;
}
li {
font-size: 18px;
padding: 4px;
}
#toast-container > .toast {
background-image: none !important;
}
#toast-container > .toast:before {
position: fixed;
font-family: FontAwesome;
font-size: 24px;
line-height: 18px;
float: left;
color: #FFF;
padding-right: 0.5em;
margin: auto 0.5em auto -1.5em;
}
#toast-container > .toast-warning:before {
content: "\f003";
}
#toast-container > .toast-error:before {
content: "\f001";
}
#toast-container > .toast-info:before {
content: "\f005";
}
#toast-container > .toast-success:before {
content: "\f002";
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />
<link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet" />
<link href="style.css" rel="stylesheet" />
</head>
<body>
<h1>Toastr with FontAwesome Icons</h1>
<ul class="icons-ul">
<li><i class="icon-li icon-ok"></i>Embedded icon using the <i> tag</li>
<li><i class="icon-li icon-ok"></i>Doesn't work with background-image</li>
<li><i class="icon-li icon-ok"></i>We can use the :before psuedo class</li>
<li><i class="icon-li icon-ok"></i>Works in IE8+, FireFox 21+, Chrome 26+, Safari 5.1+, most mobile browsers</li>
<li><i class="icon-li icon-ok"></i>See CanIUse.com for browser support</li>
</ul>
<button class="btn btn-primary" id="tryMe">Try Me</button>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
<script src="script.js"></script>
</body>
</html>
I needed to identify my toastr and I found a solution:
toastr["error"]("Message", "Alert", {
own_id: 666,
onCloseClick: function(a, b) {
// here you can update notification identified by own_id
console.log(this.own_id);
}
})
I've been working on adding a character counter to a TEXTAREA field. There are many, many solutions available online for this task.
"Stop-at-Zero" Solution
The problem I'm having is that practically all solutions terminate user input at 0. That's effective, I guess, but it's not optimal in terms of user-friendliness. For example, if a user pastes text into the TEXTAREA, and the text exceeds the field's limitation, this stop-at-zero solution will abruptly truncate the excess text. The user then has to work to find the missing content and then edit their message, submit a second form, or some other burden.
"Negative Character Count" Solution
Other solutions allow the user to enter all they want. The character counter will go from positive to negative. The problem with these counters is lack of enforcement: They allow users to submit the form even with a negative character count.
Twitter Solution
I think Twitter has it right. They let users input all they want and highlight the excess text with a negative character count (and a colored background, which I don't need to have). They disable the submit button while the count is negative.
My (Incomplete) Solution
Working with third-party code I found through Google, I've devised a character counter that works perfectly in terms of the count. But being somewhat new to JS I haven't been able to code the enforcement part.
Here's my question:
How do I get the code to prevent submission of the form when the counter is a negative number?
HTML
<form action="" method="post">
<div>
<textarea name="comments" id="comments" cols="50" rows="10"></textarea>
</div>
<div>
<input type="submit">
</div>
</form>
CSS
form div {
position: relative;
}
form .counter {
position: absolute;
left: 300px;
bottom: -25px;
font-size: 25px;
font-weight: bold;
color: #ccc;
}
form .warning {color: orange;}
form .exceeded {color: red;}
JavaScript
<script src="/js/jquery.js"></script>
<script>
(function($) {
$.fn.charCount = function(options){
// default configuration properties
var defaults = {
allowed: 100,
warning: 25,
css: 'counter',
counterElement: 'span',
cssWarning: 'warning',
cssExceeded: 'exceeded',
counterText: ''
};
var options = $.extend(defaults, options);
function calculate(obj){
var count = $(obj).val().length;
var available = options.allowed - count;
if(available <= options.warning && available >= 0){
$(obj).next().addClass(options.cssWarning);
} else {
$(obj).next().removeClass(options.cssWarning);
}
if(available < 0){
$(obj).next().addClass(options.cssExceeded);
} else {
$(obj).next().removeClass(options.cssExceeded);
}
$(obj).next().html(options.counterText + available);
};
this.each(function() {
$(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>');
calculate(this);
$(this).keyup(function(){calculate(this)});
$(this).change(function(){calculate(this)});
});
};
})(jQuery);
</script>
<script>
$(document).ready(function(){
$("#comments").charCount();
});
</script>
https://jsfiddle.net/nyc212/sk5kfopw/
I have modified your plugin to take the submit button as first parameter.
If you want it to be more dynamic:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
form div {
position: relative;
}
form .counter {
position: absolute;
left: 300px;
bottom: -25px;
font-size: 25px;
font-weight: bold;
color: #ccc;
}
form .warning {
color: orange;
}
form .exceeded {
color: red;
}
</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
(function($) {
$.fn.charCount = function(btnsub, options){
this.btnsub = btnsub;
// default configuration properties
var defaults = {
allowed: 100,
warning: 25,
css: 'counter',
counterElement: 'span',
cssWarning: 'warning',
cssExceeded: 'exceeded',
counterText: ''
};
var options = $.extend(defaults, options);
function calculate(obj,btnsub){
btnsub.attr("disabled", "disabled");
var count = $(obj).val().length;
var available = options.allowed - count;
if(available <= options.warning && available >= 0){
$(obj).next().addClass(options.cssWarning);
} else {
$(obj).next().removeClass(options.cssWarning);
}
if(available < 0){
$(obj).next().addClass(options.cssExceeded);
} else {
$(obj).next().removeClass(options.cssExceeded);
btnsub.removeAttr("disabled");
}
$(obj).next().html(options.counterText + available);
};
this.each(function() {
$(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>');
calculate(this, btnsub);
$(this).keyup(function(){calculate(this,btnsub)});
$(this).change(function(){calculate(this,btnsub)});
});
};
})(jQuery);
$(document).ready(function(){
$("#comments").charCount($("#btnsub"));
});
</script>
</head>
<body>
<form method="post">
<div>
<textarea name="comments" id="comments" cols="50" rows="10"></textarea>
</div>
<div>
<input type="submit" id="btnsub">
</div>
</form>
</body>
</html>
I would try either by disabling the submit button using the disabled attribute, or preventing the form from submitting using e.preventDefault. I updated your fiddle...just uncomment either of the options
https://jsfiddle.net/sk5kfopw/1/
I really didn't know how to come up with a descriptive title for this. Pretty much what I'm trying to do is make this accordion list item jump to the other side of the page when clicked. Currently the accordion is opening from left to right - but the last cell doesn't jump right it instead stays in place. How can I make that last cell jump to the right instead of staying in place.
The point of this is to put a picture in the tabs and have them come together at the beginning and end of browsing links.
JSFiddle Example - click the last cell
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Accordion</title>
<link rel="stylesheet" type="text/css" href="redo.css" />
</head>
<body>
<div id="hc1" class="haccordion">
<ul>
<li>
<div class="hpanel">
<div class="preview" id="p1"></div>
<div class="contentContainer">
<div class="content">
</div>
</div>
</div>
</li>
<li>
<div class="hpanel">
<div class="preview" id="p2"></div>
<div class="contentContainer">
</div>
</div>
</li>
<li>
<div class="hpanel">
<div class="preview" id="p3"></div>
<div class="contentContainer">
</div>
</div>
</li>
<li>
<div class="hpanel">
<div class="preview" id="p4"></div>
<div class="contentContainer">
asdf
</div>
</div>
</li>
<li>
<div class="hpanel">
<div class="preview" id="p5"></div>
<div class="contentContainer">
</div>
</div>
</li>
</ul>
</div>
<!-- Scripts -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript" src="accordion.js"></script>
<!-- End Scripts -->
</body>
CSS
*
{
margin:0px;
padding:0px
}
html, body
{
height:100%;
width: 100%;
}
#hc1, #hc1 ul, #hc1 li
{
height: 100%;
}
#hc1, #hc1 ul
{
width: 100%;
}
.preview
{
width: 50px;
float: left;
height: 100%;
background-color: #E48525
}
#p1{background-color: #231F20}
#p2{background-color: #4F4E4F}
#p3{background-color: #919191}
#p4{background-color: #C4C4C3}
#p5{background-color: #E8E8E8}
/*
#p1{background-color: red}
#p2{background-color: blue}
#p3{background-color: green}
#p4{background-color: black}
#p5{background-color: orange}
*/
.contentContainer
{
background-color: gray;
margin: 0 auto;
width: 100%;
height: 100%;
}
/* -- Start Accordion -- */
.haccordion{
padding: 0;
}
.haccordion ul{
margin: 0;
padding: 0;
list-style: none;
overflow: hidden; /*leave as is*/
}
.haccordion li{
margin: 0;
padding: 0;
display: block; /*leave as is*/
overflow: hidden; /*leave as is*/
float: left; /*leave as is*/
}
/* -- End Accordion -- */
Javascript
var haccordion={
//customize loading message if accordion markup is fetched via Ajax:
ajaxloadingmsg: '<div style="margin: 1em; font-weight: bold"><img src="ajaxloadr.gif" style="vertical-align: middle" /></div>',
accordioninfo: {}, //class that holds config information of each haccordion instance
expandli:function(accordionid, targetli){
var config=haccordion.accordioninfo[accordionid]
var $targetli=(typeof targetli=="number")? config.$targetlis.eq(targetli) : (typeof targetli=="string")? jQuery('#'+targetli) : jQuery(targetli)
if (typeof config.$lastexpanded!="undefined") //targetli may be an index, ID string, or DOM reference to LI
{
config.$lastexpanded.stop().animate({width:config.paneldimensions.peekw}, config.speed); //contract last opened content
config.$lastexpanded.removeClass('active');
}
$targetli.stop().animate({width:$targetli.data('hpaneloffsetw')}, config.speed) //expand current content
config.$lastexpanded=$targetli
if($targetli.attr('class') != 'active')
$targetli.addClass('active');
},
urlparamselect:function(accordionid){
var result=window.location.search.match(new RegExp(accordionid+"=(\\d+)", "i")) //check for "?accordionid=index" in URL
if (result!=null)
result=parseInt(RegExp.$1)+"" //return value as string so 0 doesn't test for false
return result //returns null or index, where index is the desired selected hcontent index
},
getCookie:function(Name){
var re=new RegExp(Name+"=[^;]+", "i") //construct RE to search for target name/value pair
if (document.cookie.match(re)) //if cookie found
return document.cookie.match(re)[0].split("=")[1] //return its value
return null
},
setCookie:function(name, value){
document.cookie = name + "=" + value + "; path=/"
},
loadexternal:function($, config){ //function to fetch external page containing the entire accordion content markup
var $hcontainer=$('#'+config.ajaxsource.container).html(this.ajaxloadingmsg)
$.ajax({
url: config.ajaxsource.path, //path to external content
async: true,
error:function(ajaxrequest){
$hcontainer.html('Error fetching content.<br />Server Response: '+ajaxrequest.responseText)
},
success:function(content){
$hcontainer.html(content)
haccordion.init($, config)
}
})
},
init:function($, config){
haccordion.accordioninfo[config.accordionid]=config //cache config info for this accordion
var $targetlis=$('#'+config.accordionid).find('ul:eq(0) > li') //find top level LIs
config.$targetlis=$targetlis
config.selectedli=config.selectedli || [] //set default selectedli option
config.speed=config.speed || "normal" //set default speed
//KEY_CHANGE_BEGIN
var maxWidth = $targetlis.parent ().width ();
$targetlis.each ( function () { maxWidth -= $(this).outerWidth (true); } );
$targetlis.each(function(i){
var $target=$(this).data('pos', i) //give each li an index #
var lclMaxWidth = maxWidth + $target.find ('.hpanel:eq(0)').outerWidth (true);
$target.css ('width', config.paneldimensions.fullw);
//get offset width of each .hpanel DIV (config.dimensions.fullw + any DIV padding)
var hpaneloffsetw = $target.find ('.hpanel:eq(0)').outerWidth (true);
if (hpaneloffsetw > lclMaxWidth)
hpaneloffsetw = lclMaxWidth;
$target.data('hpaneloffsetw', hpaneloffsetw);
$target.css ('width', '');
//KEY_CHANGE_END
$target.click(function(){
haccordion.expandli(config.accordionid, this)
config.$lastexpanded=$(this);
})
if (config.collapsecurrent){ //if previous content should be contracted when expanding current
config.$lastexpanded.removeClass('active');
$target.click(function(){
$(this).stop().animate({width:config.paneldimensions.peekw}, config.speed); //contract previous content
})
}
}) //end $targetlis.each
var selectedli=haccordion.urlparamselect(config.accordionid) || ((config.selectedli[1] && haccordion.getCookie(config.accordionid))? parseInt(haccordion.getCookie(config.accordionid)) : config.selectedli[0])
selectedli=parseInt(selectedli)
if (selectedli>=0 && selectedli<config.$targetlis.length){ //if selectedli index is within range
config.$lastexpanded=$targetlis.eq(selectedli)
config.$lastexpanded.css('width', config.$lastexpanded.data('hpaneloffsetw')) //expand selected li
}
$(window).bind('unload', function(){ //clean up and persist on page unload
haccordion.uninit($, config)
}) //end window.onunload
},
uninit:function($, config){
var $targetlis=config.$targetlis
var expandedliindex=-1 //index of expanded content to remember (-1 indicates non)
$targetlis.each(function(){
var $target=$(this)
$target.unbind()
if ($target.width()==$target.data('hpaneloffsetw'))
expandedliindex=$target.data('pos')
})
if (config.selectedli[1]==true) //enable persistence?
haccordion.setCookie(config.accordionid, expandedliindex)
},
setup:function(config){
//Use JS to write out CSS that sets up initial dimensions of each LI, for JS enabled browsers only
document.write('<style type="text/css">\n')
document.write('#'+config.accordionid+' li{width: '+config.paneldimensions.peekw+';\nheight: '+config.paneldimensions.h+';\n}\n')
document.write('#'+config.accordionid+' li .hpanel{width: '+config.paneldimensions.fullw+';\nheight: '+config.paneldimensions.h+';\n}\n')
document.write('<\/style>')
jQuery(document).ready(function($){ //on Dom load
if (config.ajaxsource) //if config.ajaxsource option defined
haccordion.loadexternal($, config)
else
haccordion.init($, config)
}) //end DOM load
}
}
haccordion.setup({
accordionid: 'hc1', //main accordion div id
paneldimensions: {peekw:'50px', fullw:'100%', h:'100%'},
selectedli: [4, false], //[selectedli_index, persiststate_bool]
collapsecurrent: false //<- No comma following very last setting!
})
Here it is: tinker.io/f7fe4/12
This is the simplest change of all of the versions, requiring only floating the first preview to the right. Can be done programatically or with css (can be buggy in IE7+):
$('#hc1 li .preview').first().css('float','right');
or
#hc1 li:first-child .preview {
float:right;
}
--
Is this the kind of effect you're looking for?
https://tinker.io/f7fe4/8
Here's the same kind of affect, with a 'smoother' animation (it keeps the outer div still on the screen however)
https://tinker.io/f7fe4/9
And this is what I thought you were talking about at first
https://tinker.io/f7fe4/4 (this pops the left most cell over to the right and opens it, kind of like an infinite slider)