I am using jQuery.ProfanityFilter to find swear words in a page. The code is below:
$divs.profanityFilter({
customSwears: ['drunk'],
externalSwears: 'swearWords.json',
filter: false,
profaneText: function (data) {
alert("swear!");
}
});
My question is would there be any way of counting the amount of swear words that are found? I cannot seem to find a suitable way of adapting the code.
Any help would be greatly appreciated.
You may be able to modify your plugin slightly. Based on the link presented by #DontVoteMeDown, you may be able to manually change the profaneText function in the plugin file directly to work with your implementation of it.
In the Plugin File
if (profane) {
options.profaneText(data.unique(), data.length);
};
Then in your own JQuery implementation of the plugin:
$divs.profanityFilter({
customSwears: ['drunk'],
externalSwears: 'swearWords.json',
filter: false,
profaneText: function (data, size) {
console.log("Swear words in element: " + data);
console.log("Number of swear words: " + size);
}
});
Use a global counter variable.
var swears = 0;
$divs.profanityFilter({
customSwears: ['drunk'],
externalSwears: 'swearWords.json',
filter: false,
profaneText: function (data) {
swears++;
alert("swear!");
}
});
Related
Need to know how I could possibly save the state of the darkmode?
I got this js code right here:
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
$('body').addClass('dark');
$('main').addClass('darklight');
$('footer').addClass('darklight');
$('.topnav').addClass('darklight');
$('.lightm').addClass('darklight');
$('section').addClass('darklight');
$('button').addClass('button');
$('.links').addClass('llinks');
} else {
$('body').removeClass('dark');
$('body').addClass('light');
$('main').removeClass('darklight');
$('main').addClass('light');
$('footer').removeClass('darklight');
$('footer').addClass('light');
$('.topnav').removeClass('darklight');
$('.topnav').addClass('light');
$('.lightm').removeClass('darklight');
$('.lightm').addClass('light');
$('section').removeClass('darklight');
$('section').addClass('light');
$('button').removeClass('button');
$('button').addClass('dbutton');
$('.links').removeClass('llinks');
$('.links').addClass('dlinks');
}
})
Here is the code in Codepen with the html and css things:
https://codepen.io/TRGYT/pen/eYmNBPo
Does anyone have idea on how to achieve this? And can this darkmode state also be saved for other sites I created?
Please find the site here:
https://15min.netlify.com
Sorry in advance for the bad code, I'm a beginner...
Welcome to the world of coding. Before we get to the problem, it will be of some use to you to get to grips with the DRY principle (Don't Repeat Yourself). Your code (20 or so lines) could easily be abbreviated to just four. For example:
$("#switch").on("click", () => {
$("body").toggleClass("dark"));
// Local storage. Will get to this later
});
You could then change your CSS to respond to whether or not the body tag has the dark class. Much cleaner.
As for saving the state of the dark mode: use window.localStorage like so:
if (window.localStorage) {
const darkMode = window.localStorage.getItem("darkMode");
if (darkMode) {
$("body").addClass("dark");
} else {
$("body").removeClass("dark");
}
}
I found a way that wored. The one answer I got helped me understand it, but I was too lazy to implement it. But still thank you!
function activateDarkMode() {
$('body').addClass('dark').removeClass('light');
$('main').addClass('darklight').removeClass('light');
$('footer').addClass('darklight').removeClass('light');
$('.topnav').addClass('darklight').removeClass('light');
$('.lightm').addClass('darklight').removeClass('light');
$('section').addClass('darklight').removeClass('light');
$('button').addClass('button').removeClass('button');
$('.links').addClass('llinks').removeClass('dlinks');
}
function deactivateDarkMode() {
$('body').removeClass('dark').addClass('light');
$('main').removeClass('darklight').addClass('light');
$('footer').removeClass('darklight').addClass('light');
$('.topnav').removeClass('darklight').addClass('light');
$('.lightm').removeClass('darklight').addClass('light');
$('section').removeClass('darklight').addClass('light');
$('button').removeClass('button').addClass('dbutton');
$('.links').removeClass('llinks').addClass('dlinks');
}
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
activateDarkMode();
localStorage.setItem("darkmode", "enabled")
} else {
deactivateDarkMode();
localStorage.setItem("darkmode", "disabled")
}
});
let mode;
mode = localStorage.getItem("darkmode");
if (mode == 'enabled') {
activateDarkMode();
$('#switch').prop('checked', 'checked');
}
All I did was putting the addClass and removeClass into a function. He also added the localStorage and let the localStorage be in a variable called mode. After I created these things, I put them into an if to check if the darkmode is turned on or not.
We have an application running that currently works with both 3D and 2D files, and do not experience any issues when loading 3D files and DWG.
But when trying to load a PDF neither my "onItemLoadSuccess" or "onItemLoadFail" gets run
Autodesk.Viewing.Initializer(options, function onInitialized() {
// Select the container for the viewer
viewerApp = new Autodesk.Viewing.ViewingApplication(container);
// Load settings, i.e extension manager
viewerApp.registerViewer(viewerApp.k3D,
Autodesk.Viewing.Private.GuiViewer3D, { extensions: [ 'ExtensionManager'] });
// Select model to load defined by URN
viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
function onDocumentLoadSuccess(doc) {
var viewables = viewerApp.bubble.search({ 'type': 'geometry' });
if (viewables.length === 0) {
console.error('Document contains no viewables.');
return;
}
// Choose any of the avialble viewables
viewerApp.selectItem(viewables[0], onItemLoadSuccess, onItemLoadFail);
}
function onItemLoadSuccess(viewer, item) {
console.log('onItemLoadSuccess()!');
}
function onItemLoadFail(errorCode) {
console.error('onItemLoadFail() - errorCode:' + errorCode);
}
The PDF file will still open and load, so I am wondering if there might be a different way to run an onItemLoadSuccess function, or we have to do something a bit differently to ensure that our PDF's also gets loaded correctly.
Any help is highly appreciated!
Starting from Viewer v6.3 you can load PDF directly with Autodesk.PDF and pass in callbacks to loadModel like you do other models:
Autodesk.Viewing.Initializer(options, function() {
viewer.start()
viewer.loadExtension('Autodesk.PDF').then(function() {
viewer.loadModel('/path/to/pdf', { page: 1 }, onLoadSuccess, onLoadFail);
});
});
See release notes here: https://forge.autodesk.com/blog/viewer-release-notes-v-63
(Adding to Bryan's answer...)
I wrote a blog post about this. Take a look at the DEMO and sample code to help answer your question about 'onItemLoadSuccess / onItemLoadFail' events.
BLOG: https://forge.autodesk.com/blog/fast-pdf-viewingmarkup-inside-forge-viewer
DEMO: https://wallabyway.github.io/offline-pdf-markup/
Hope that helps!
I want to have a button that can turn on and off the 'hints' function in intro.js.
I have a working version to show and then hide but the show only works once. How can I get it to work repeatedly? This functionality works for the standard data-intro but not for data-hint.
<div class="jumbotron">
<h1 id='step1'>Hints</h1>
<p class="lead">Adding hints using JSON + callbacks</p>
<a id='step2' class="btn btn-large btn-success" href="javascript:void(0);">Add hints</a>
</div>
function addHints(){
intro = introJs();
intro.setOptions({
hints: [
{
element: document.querySelector('#step1'),
hint: "This is a tooltip.",
hintPosition: 'top-middle'
},
{
element: '#step2',
hint: 'More features, more fun.',
position: 'left'
},
{
element: '#step4',
hint: "<b>Another</b> step.",
hintPosition: 'top-middle'
}
]
});
intro.onhintsadded(function() {
console.log('all hints added');
});
intro.onhintclick(function(hintElement, item, stepId) {
console.log('hint clicked', hintElement, item, stepId);
});
intro.onhintclose(function (stepId) {
console.log('hint closed', stepId);
});
intro.addHints();
}
$(function() {
$('#step2').click(function(){
if ( $('#step2').hasClass('clicked') ) {
introJs().hideHints();
$('#step2').removeClass('clicked');
} else {
addHints();
$('#step2').addClass('clicked');
}
});
});
Instead of using hideHints intro.js API method just remove the div block of intro.js from DOM:
var introDiv = document.getElementsByClassName("introjs-hints")[0];
introDiv.parentNode.removeChild(introDiv);
(You can do the same thing with jQuery if you want to).
When the div is removed from DOM, just initialize hints once again as you do with your addHints method when you want to show hints and it'll work.
Instead of deleting the div block with javascript. You can use .removeHints()
This function is part of intro.js, but is not included in the documentation.
Perhaps a bit hacky, but this works for me...
First, put your hints into their own variable:
hints = [{...}, ...]
then, reset your hints in the intro options
intro.onhintclose(function(stepId) {
if (document.querySelectorAll('.introjs-hidehint').length === hints.length) {
intro.setOptions({hints: hints})
}
})
The hidden hints are given a class of introjs-hidehint, and document.querySelectorAll will return all of them in an array. Once that array is the same size as your hints array, reset your hints in your intro options and that will reset all your hints so you can show them all again.
Here's a more complete example that also allows:
(a) toggling hints on/off by clicking a button (located on a nav bar so used across multiple pages).
(b) once all hints have been clicked, the hints div gets removed so that clicking show hints button will again actually...show hints...
(c) allow you to store hints for multiple pages in a single json object array (re: nav bar).
var jquery = require('jquery');
var introJs = require('intro.js');
* ===========================================================================
* define onclick of hints button
* =========================================================================*/
jquery('#hints_button').on('click', function() {
if (document.getElementsByClassName('introjs-hints').length == 0){
addSomeHints();
}
else {
destroyHints();
};
});
/* ===========================================================================
* Add hints using the IntroJS library
* =========================================================================*/
/* define hints */
var theHints = [
{
element: document.querySelector('#step1'),
hint: "This is a tooltip.",
hintPosition: 'top-middle'
},
{
element: '#step2',
hint: 'More features, more fun.',
hintPosition: 'left'
},
{
element: '#step4',
hint: "<b>Another</b> step.",
hintPosition: 'top-middle'
}
];
/* generate hints with introjs */
function addSomeHints() {
intro = introJs();
intro.setOptions({
hints: theHints
});
intro.onhintclose(function (stepId) {
var remaining_hints = all_hints - document.getElementsByClassName("introjs-hidehint").length;
if (remaining_hints == 0) {
destroyHints();
};
});
/* add hints */
intro.addHints();
/* store number of hints created */
var all_hints = document.getElementsByClassName('introjs-hint').length;
};
/* remove hints div */
function destroyHints() {
var hintsDiv = document.getElementsByClassName("introjs-hints")[0]
hintsDiv.parentNode.removeChild(hintsDiv);
};
... hopefully this saves someone the 20 minutes it took me to piece together the answers and adapt it for what seems like a super common use case.
Let me just preface by saying it's actually my crappy code that's leaking and crashing my browser, I just thought I better make the languages being used as clear as I could from the outset.
I have a test page here and the javascript can be found here. My problem is that when I try and drag and drop either one of the red pieces more than a few times it sucks up all browser resources and crashes the browser. I'm fairly certain the culprit is something in the following function in the Tracker() object but I'm absolutely stuck on how to debug this.
My current most likely culprit:
function register_draggable(ob) {
ob.config.jqId.draggable({cursor: 'move',
grid:[ob.config.size, ob.config.size],
containment: '#chessboard',
revert: 'invalid',
start: function() {
check_allowable_moves(ob.config.jqLocation,
ob.config.jqId,
ob);
},
stop: function() {
remove_allowable_moves();
}
});
}
If anyone could take a quick look and give me any suggestions on what I should be looking for, it would be enormously appreciated.
Solution
Turns out register_draggable() was the culprit. I registered a new draggable every time the location of a piece updated and all those draggables on the same object were doing nasty things.
Currently I now explicity destroy the old draggable before creating a new one. Current code is
function register_draggable(ob) {
ob.config.jqId.draggable('destroy');
ob.config.jqId.draggable({cursor: 'move',
grid:[ob.config.size, ob.config.size],
containment: '#chessboard',
revert: 'invalid',
start: function() {
check_allowable_moves(ob.config.jqLocation,
ob.config.jqId,
ob);
},
stop: function() {
remove_allowable_moves();
}
});
}
I don't think this is actually your problem, but it seems like your making an extra method call on register and check_ allowable_moves
return {
register_map: function(ob) { map = ob; },
register_piece: function(ob) {
ob.config.tracker = this;
register_draggable(ob);
},
register_draggable: function(ob) { register_draggable(ob); },
check_allowable_moves: function(location, jqPiece, ob) { check_allowable_moves(location, jqPiece, ob); }
}
can be shortened to
return {
register_map: function(ob) { map = ob; },
register_piece: function(ob) {
ob.config.tracker = this;
register_draggable(ob);
},
register_draggable: register_draggable,
check_allowable_moves: check_allowable_moves
}
Also
you are doing a double lookup here:
function remove_allowable_moves() {
$('.allowable').droppable('destroy');
$('.allowable').removeClass('allowable');
}
should be
function remove_allowable_moves() {
$('.allowable').droppable('destroy')
.removeClass('allowable');
}
Also
Whats the purpose of parsing and int into a float? Take off the parseFloat.
var x = parseInt(locs[1]);
var y = parseInt(locs[2]);
var x_min = parseFloat(x)-2;
var y_min = parseFloat(y)-2;
Finally
Why are you re-registering as draggable on drop? This could be the culprit, if your registering the draggable multiple times and only destroying it once.
jqCell.droppable({ accept: '#'+jqPiece.attr('id'),
drop: function(ev, ui) {
ob.config.jqLocation = $(this);
register_draggable(ob); // why this?
}
});
Other thoughts
Another thing I don't know if its going to help your performance, but it could clean up your code. the jquery selector allows commas so instead of
$('#coord-1-1').doStuff();
$('#coord-1-2').doStuff();
$('#coord-1-3').doStuff();
you could do
$('#coord-1-1, #coord-1-2, #coord-1-3').doStuff();
so your loop would only be concerned with generating the selector string and then you could run you operation on the entire set.
IMO a cleaner init
instead of
var map = new Map('content');
var piece1 = new Piece(map);
var piece2 = new Piece(map);
var tracker = new Tracker;
tracker.register_map(map);
map.render();
piece1.render('coord-4-4', '1');
piece2.render('coord-1-1', '2');
tracker.register_piece(piece1);
tracker.register_piece(piece2);
I'd like to see
$(document).ready(function() {
$('#content').MapGame({
pieces : { '1' : 'coord-4-4', '2' : 'coord-1-1' }
});
});
Now implementing that is a strech from what you have now, but when building a component for jQuery I like to start with a simple init and work from their. Thats one of the big goals of jQuery is to hide all the junk from the user and just let them spin up and instance of your plugin easily.
It feels like some event-handlers are registered multiple times, but I'm unsure. (Reason below.)
That doesn't answer the question, but you absolutely should put as much code outside of $(document).ready(…) as possible, in no case put all your code in there as you do now.
I fear that your code is so ineligible that it's too much work to understand it. Could you restructure it (All those function-in-function are really horrible to read.) and add some comments.
Maybe it's just me, but I find it too hard to read and understand. It's surely going to be a disaster to maintain.
I have made a simple accordion for my site using jQuery... It worked great, but I've recently started working on a change where if you click the currently opened segments title (the clickable area to slide up/down), it should close the current section.
var sideMenu = {
activated: {},
setup: function() {
$('.menu-category-heading').bind('click', function() {
sideMenu.slideMenu($('ul', $(this).parent()));
});
},
slideMenu: function(menuObj) {
if (sideMenu.activated == menuObj) {
$(sideMenu.activated).slideUp(400);
sideMenu.activated = null;
console.log('same');
} else {
$(sideMenu.activated).slideUp(400);
menuObj.slideDown(500);
sideMenu.activated = menuObj;
console.log('new');
}
}
}
For some reason the comparison is never working... it does if I add $(menuObj).attr('id') and the same for activated. But this is not ideal as not all items will have an id attribute.
Any suggestions as to make the object comparison work? Or any other tips?
Thank you!
You are probably saving a jQuery object (the result of a $ call) rather than the native element. Each time you do a $(myEl) a new object is created and the references will not match up, but the native element will. Try:
if (slideMenu.activated[0] == menuObj[0]) {
...
}