Noty.js removing oldest notification on new notification - javascript

I am using this script http://ned.im/noty/
for showing notifications
var n = noty({
text: message,
type: type,
dismissQueue: true,
force: true,
layout : "bottomLeft",
theme: 'newTheme',
maxVisible : 5
});
So this is the current config, it has queued 5 items. The problem is that I can't figure out how to remove the first notification on showing new one, when a button is clicked.
Any ideas are welcome.

Okay I figured it out using the noty.js API: http://ned.im/noty/#api
first I defined the top notification
var notyclose_id = $("#noty_bottomLeft_layout_container>li:first-child>.noty_bar").attr('id');
after that I get the amount of notifications
var noty_list_count = $("#noty_bottomLeft_layout_container li").size();
than I check if this amount is bigger or equal to my notifications setting
if(noty_list_count >= 5)
$.noty.close(notyclose_id);
and if yes I use the api to close it. :)

Was looking for this and ended up here; current version for the time being (3.1.0) allows you to use the killer option:
noty({
text: 'I have just killed it',
type: 'success',
killer : true
})
Looks like it "kills" all previous notifications in the queue, making "this one" the only one displayed.

You can also consider an auto removal timeout. That's what I do with information and success messages: they disappear automatically after 3 seconds (timeout: 3000). I leave the error and warning messages permanent (user has to click it to be removed, timeout: false, that's the default).
This way it's less likely that things pile up and requires less user interaction. Less friction. I don't know if it fits your use-case though.
noty({
text: 'Sucessfully persisted xy value',
layout: 'bottomRight',
type: 'success',
timeout: 3000,
animation: {
open: 'animated zoomInUp', // Animate.css class names
close: 'animated zoomOutUp' // Animate.css class names
}
});
noty({
text: 'Error while writing value xy',
layout: 'bottomRight',
type: 'error',
animation: {
open: 'animated zoomInUp', // Animate.css class names
close: 'animated zoomOutUp' // Animate.css class names
}
});

if your are using layout as 'topRight' then given below code is helpful.
var notyclose_id = $("#noty_topRight_layout_container>li:first- child>.noty_bar").attr('id');
var noty_list_count = $("#noty_topRight_layout_container li").size();
if(noty_list_count >= 6) {
$.noty.close(notyclose_id);
}
you also need to call $.notyRenderer.show() to show a new message, it's already there but you need to call it everytime
if(instance.options.maxVisible > 0) {
//if($(instance.options.layout.container.selector + ' > li').length < instance.options.maxVisible) {
$.notyRenderer.show($.noty.queue.shift());
//}
//else {
//}
}

Related

Repeat JS Textillate function each time modal is opened

I am using uikit modal on a project. I am also using JS Textillate to animate the text when the modal is opened. However, I want the text to be animated if the modal is closed and opened again continuously. For now, it only animate once when the modal is opened for the first time, when closed and opened again, the animation does not run again.
This is the JavaScript code below:
$(".uk-modal-full").on('show', function(){
var $title = $(".txt").textillate({
// in animation settings.
in: {
effect: "fadeIn", // set the effect name
},
// out animation settings.
out: {
effect: "fadeOut",
delayScale: 0,
delay: 0,
},
type: "char",
autoStart: true,
});
var $title = $(".txt2").textillate({
// in animation settings.
in: {
effect: "fadeIn", // set the effect name
},
// out animation settings.
out: {
effect: "fadeOut",
delayScale: 0,
delay: 0,
},
type: "char",
autoStart: true,
});
});
I am thinking maybe the function can be removed when modal closes so that it can be repeated when it is opened again. I am not sure if that is possible as I am only a Jquery learner.
$(".uk-modal-full").on('hide', function(){
// code here?
});
Full options for Textillate is here https://github.com/jschr/textillate
UPDATE
Thank you! I have created a codepen here to test my full code inside a modal using your example. It seems to be working but with some issues. When I use $element.textillate('in') and $element.textillate('out'), the other options do not work (e.g. initialDelay). It seems to only control the "in" and "out" options. When I used $element.textillate('start') and $element.textillate('stop'), the other options worked but when modal is reopened, the text are briefly loaded first before animating.
Please see codepen here - https://codepen.io/ajaxthemestudios/pen/XWJRBbW
Looking through the readme of Textillate, I think this section is what you need:
$element.textillate('start') - Manually start/restart textillate
$element.textillate('stop') - Manually pause/stop textillate
$element.textillate('in') - Trigger the current text's in animation
$element.textillate('out') - Trigger the current text's out animation
So I would do something like first define the animations (outside the event functions)
var title1 = $(".txt").textillate({
// in animation settings.
in: {
effect: "fadeIn", // set the effect name
},
// out animation settings.
out: {
effect: "fadeOut",
delayScale: 0,
delay: 0,
},
type: "char",
autoStart: false,
});
var title2 = $(".txt").textillate({
// in animation settings.
in: {
effect: "fadeIn", // set the effect name
},
// out animation settings.
out: {
effect: "fadeOut",
delayScale: 0,
delay: 0,
},
type: "char",
autoStart: false,
});
And then in the event function:
$(".uk-modal-full").on('show', function(){
title1.textillate('in');
title2.textillate('in');
}
EDIT
I got it to work in this codepen: https://codepen.io/thomas-short/pen/zYxdzWY
Test it by clicking on click repeatedly.
EDIT 2
The problem of the text being briefly visible seems to be a limitation of the library. I could not find a way to solve it using the tools they provide. The only way I managed to make it work is by control it myself:
$(".uk-modal-full").on('show', function(){
title1.textillate('start');
$(".txt2").hide();
setTimeout(() => {
$(".txt2").show();
title2.textillate('start');
}, 1500);
})
And remove initialDelay from the options

JS-Plumb: (Re-)Draw a line between two elements after clicking

Edit: After trying out different hand-made solutions, I am using JSPlumb and trying to let it visually connect a clicked item from one list with a clicked item from another list (see screenshot).
I built upon this Stackoverflow thread and made it work basically, however the code provided there allows multiple connections, i.e. JSPlumb draws multiple endpoints and lines, and it doesn't react if a 'Target' is clicked first.
However, in my case there should be strictly only one connection, and JSPlumb should re-connect once I click on another list item on either side.
(E.g. I click on 'Source 1' and 'Target 3', JSPlumb draws the connection. I click on 'Target 4', JSPlumb should keep 'Source 1' as source and re-set 'Target 4' as the target, e.g. now draw the connection from 'Source 1' to 'Target 4'. The same with clicking a different 'Source', i.e. the target should stay the same.)
In what way would I need to alter the code in order to achieve the desired re-draw?
CodePen
jQuery(document).ready(function () {
var targetOption = {
anchor: "LeftMiddle",
isSource: false,
isTarget: true,
reattach: true,
endpoint: "Dot",
connector: ["Bezier", {
curviness: 50}],
setDragAllowedWhenFull: true
};
var sourceOption = {
tolerance: "touch",
anchor: "RightMiddle",
maxConnections: 1,
isSource: true,
isTarget: false,
reattach: true,
endpoint: "Dot",
connector: ["Bezier", {
curviness: 50}],
setDragAllowedWhenFull: true
};
jsPlumb.importDefaults({
ConnectionsDetachable: true,
ReattachConnections: true,
Container: 'page_connections'
});
//current question clicked on
var questionSelected = null;
var questionEndpoint = null;
//remember the question you clicked on
jQuery("#select_list_lebensbereiche ul > li").click( function () {
//remove endpoint if there is one
if( questionSelected !== null )
{
jsPlumb.removeAllEndpoints(questionSelected);
}
//add new endpoint
questionSelected = jQuery(this)[0];
questionEndpoint = jsPlumb.addEndpoint(questionSelected, sourceOption);
});
//now click on an answer to link it with previously selected question
jQuery("#select_list_wirkdimensionen ul > li").click( function () {
//we must have previously selected question
//for this to work
if( questionSelected !== null )
{
//create endpoint
var answer = jsPlumb.addEndpoint(jQuery(this)[0], targetOption);
//link it
jsPlumb.connect({ source: questionEndpoint, target: answer });
//cleanup
questionSelected = null;
questionEndpoint = null;
}
});
});
You were already keeping track of the "source" end of the linked items in a global variable; one way of getting to your desired behavior mostly just requires keeping track of the "target" end the same way. (There's room for improving this -- globals are maybe not an ideal strategy, and there's some code duplication between the 'source' and 'target' click handlers, but this should do for demonstration at least.)
// ...other init variables skipped
var questionEndpoints = []; // 'source' and 'target' endpoints
// "source" click handler
jQuery("#select_list_lebensbereiche ul > li").click(function() {
//remove existing start endpoint, if any:
jsPlumb.deleteEndpoint(questionEndpoints[0]);
// add a new one on the clicked element:
questionEndpoints[0] = jsPlumb.addEndpoint(jQuery(this), sourceOption);
connectEndpoints();
});
// "target" endpoint
jQuery("#select_list_wirkdimensionen ul > li").click(function() {
if (!questionEndpoints[0]) return; // don't respond if a source hasn't been selected
// remove existing endpoint if any
jsPlumb.deleteEndpoint(questionEndpoints[1]);
//create a new one:
questionEndpoints[1] = jsPlumb.addEndpoint(jQuery(this), targetOption);
connectEndpoints();
});
var connectEndpoints = function() {
jsPlumb.connect({
source: questionEndpoints[0],
target: questionEndpoints[1]
});
};
});
Working CodePen example

Enable Second typeit only after first is complete

I am trying to include typing effect on my website. For that I was trying to use TypeIt, a JS Library for it.
I am able to make it work but the problem is I want the second TypeIt instance to run only when the first is complete.
As in their Documentation there is a method called instance.isComplete
Here is how I was trying it.
HTML
<p id="example1"></p>
<p id="example2"></p>
The JavaScript is
var instance = new TypeIt('#example1', {
strings: ["FIRST TEXT"],
speed: 75,
autoStart: true
});
while(1)
{
if(instance.isComplete)
{
new TypeIt('#example2', {
strings: ["TEXT TO APPEAR AFTER FIRST IS COMPLETE"],
speed: 75,
autoStart: true
});
break;
}
}
I was trying to use a loop that will break once the instance is complete but the problem is I am stuck in an Infinite Loop and page won't load
You can place your second call in the afterComplete property when you declare the options for the first one; however, I feel like there's probably a better way to do this. You might want to go over the documentation again.
var instance = new TypeIt('#example1', {
strings: ["FIRST TEXT"],
speed: 75,
autoStart: true,
afterComplete: function(instance){
instance.destroy();
new TypeIt('#example2', {
strings: ["TEXT TO APPEAR AFTER FIRST IS COMPLETE"],
speed: 75,
autoStart: true
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeit/5.10.1/typeit.min.js"></script>
<p id="example1"></p>
<p id="example2"></p>
Edit:
Here is the effect I think you're going for:
var instance = new TypeIt('#example1', {
speed: 75,
autoStart: true
})
.type('FIRST TEXT')
.break()
.type('TEXT TO APPEAR AFTER FIRST IS COMPLETE');
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeit/5.10.1/typeit.min.js"></script>
<p id="example1"></p>
<p id="example2"></p>
The documentation site had a demo codepen

Resizing a responsive DataTable is very slow, how can I speed it up?

I have a DataTable which has a couple of thousand records in it.
I have the responsive plugin for it, and the responsive option is enabled.
I also tried enabling the deferRender option, but this appeared to have no impact on the time taken.
When I resize the browser there is a delay of 1s - 2s. This happens in IE11, and MS Edge. The performance in chrome isn't fantastic, but at 0.5s it's tolerable.
I am using custom ordering functions, but those functions are omitted for brevity. I'm fairly sure I know where the issue is, and it's not in them. I can provide them if required.
Here's my initialisation code:
this._dataTable = $("#listtable").DataTable({
paging: true,
responsive: true,
deferRender: true,
columns: [{
title: "Name",
data: "thing.name"
}, {
title: "State 1",
data: "state1",
type: "state1",
render: (data, type, row, meta) => {
return this._renderState1(data, meta);
}
}, {
title: "State 2",
data: "state2",
type: "state2",
render: (data, type, row, meta) => {
return this._renderState2(data, meta);
}
}]
});
I load the data by calling dataTable.row.add for each item, and then calling dataTable.draw at the end.
The performance issues occur after all the data has been successfully loaded, so I don't think it's to do with that.
Digging further in to the profiler information I found that it was the rendering of the rows that was the issue:
By commenting out code in my custom render functions shown in the initalisation code, I found that the issue lay with finding the containing cell to set the background colour:
var cell = this._dataTable
.cell({ row: meta.row, column: meta.col })
.node();
Here's the rest of the code for setting the background colour:
var cellClass = this._getStateClass(state);
$(cell).addClass(cellClass);
If I comment the cell retrieval line out then the performance isn't amazing, but it is acceptable.
So my question is how can I have a custom background colour for cells while maintaing the responsive performance?
A fast alternative to dataTable.cell would do, as would an alternative approach to setting the background colour.
I managed to solve this issue by removing the need to find the cell.
I put a class on the columns that removed the padding they have.
Style:
.cell-state1 {
padding: 0;
}
Configuration:
this._dataTable = $("#listtable").DataTable({
paging: true,
responsive: true,
deferRender: true,
columns: [{
title: "Name",
data: "thing.name"
}, {
title: "State1",
data: "state1",
type: "state1",
className: "cell-state1",
render: (data, type, row, meta) => {
return this._renderState1(data, meta);
}
}]
});
Then I changed my render functions so they returned the content in a div which filled the cell, had the background colour, and added the padding back in.
Style:
.cell-state1-somestate {
height: 100%;
width: 100%;
padding: 8px;
background-color: #000000;
color: #ffffff;
}
Render Function:
function _renderState1 (state1) {
var cssClass = _this._getState1CellClass(state1);
var text = _this._getState1CellText(state1);
var content = "<div class='" + cssClass + "'>" + text + "</div>";
return content;
};
This left me with one final issue.
I have custom order functions, and now rather than being passed the text value they're passed the div containing the text value.
I used a little bit of jQuery to extract the text:
var floodAlertSeverity = $(content).html();.
It'd be nice if the order functions received the original data, rather than the rendered data, but oh well.
I had a similar issue with IE11 becoming extremely slow when resizing the browser window in responsive mode, which made for a pretty terrible user experience.
I don't have the time nor the expertise to fix the underlying issue (probably just IE11 being slow), but I came up with an elegant hack to work around the problem, which is basically to throttle the calls to the function that adjusts the column sizes.
The performance profiler in IE11 showed that calls to _fnAdjustColumnSizing(oSettings); were taking most of the CPU time, and the calls to this method are triggered by the 'resize.DT-YourTableNameHere' event, so using a simple timer we can delay the call to this function until the user is done resizing the window:
var dtResizeTimer;
var allowPropagation = false;
$(window).on("resize.DT-visitsTable", function (event) {
if (allowPropagation === false) {
event.stopImmediatePropagation();
clearTimeout(dtResizeTimer);
dtResizeTimer = setTimeout(function() {
allowPropagation = true;
$(window).trigger("resize.DT-visitsTable");
}, 100);
} else {
allowPropagation = false;
}
});
Obviously you'll need to replace visitsTable with whatever id you gave to your table element.
It still takes a second for IE11 to update the table after the user is done resizing, but at least the resizing itself is now smooth. There might be a better solution, but for now, this calms my frustration with IE11.

Display tour for first time user

I am trying to make a guided tour for the first time user of my site. It works perfectly on localhost, but when I upload it onto my dev server it doesn't work properly i.e. the tooltips are not at the designated place. See the following two screenshots -
I think the issue is because the component is not loaded so far i think so the rendering of the tooltip happens in the middle of the page.
Repository I am using is here
Code - Controller
$scope.IntroOptions = {
steps:[
{
element: '#step1',
intro: "<b>First Step First: </b>Click here to define structure of your test scripts!!<br/>You can modify this later on any time",
position: 'left'
},
{
element: '#step2',
intro: "Click here to select a folder/test script spreadsheet from google drive.",
position: 'bottom'
}]
,
showStepNumbers: false,
exitOnOverlayClick: false,
exitOnEsc: false,
nextLabel: '<strong>NEXT!</strong>',
prevLabel: '<span style="color:green">Previous</span>',
skipLabel: 'Exit',
doneLabel: 'Thanks!'
};
$scope.ShouldAutoStart = false;
$timeout(function(){
$scope.CallMe();
}, 0);
HTML code -
<div ng-controller="tourController" class="container-narrow">
<div ng-intro-options="IntroOptions" ng-intro-method="CallMe"
ng-intro-oncomplete="CompletedEvent" ng-intro-onexit="ExitEvent"
ng-intro-onchange="ChangeEvent" ng-intro-onbeforechange="BeforeChangeEvent"
ng-intro-onafterchange="AfterChangeEvent"
ng-intro-autostart="ShouldAutoStart">
</div>
</div>
**I tried using angular.element(document).ready() also but its not working.
Things are working now with timeout 1000 mili secs but i think there
must be a better way of doing this

Categories