I'm working with a jQuery plugin, and it has some unusual coding that I think might be kinda old school. For the sake of my own education, I'm hoping you guys and gals can give me some clarification.
First, I see this:
var $elem = jQuery(this);
I've never seen jQuery(this)... is it the same as $(this)? I did some tests and they appear to be the same, but later in the script the author uses $(this)... so why did he use jQuery(this) in one part and $(this) later?
And is there a reason he used $elem instead of just elem?
Second, I see a function like this:
;(function($) {
var foo = {
bar : 'a',
example : 'b'
}
function whatever(event) {
...
}
})(jQuery);
I've never seen ;(function($) { ... })(jQuery), what's the actual purpose of this? There are several other variables and functions in it, I just abbreviated it here for the post.
On mobile devices, I load a script named "mobile.js" in the header. This script has functions to detect a swipe and a taphold (which I believe were both recommended on here), and then I also include a function to hide a specific element when the user focuses on an input, textarea, or contenteditable:
$(function() {
if ($('#local_banner').css('display') != 'none') {
$('input, textarea, [contenteditable]')
.on('focus', function() {
console.log('a');
$('#local_banner').hide();
})
.on('blur', function() {
console.log('b');
$('#local_banner').show();
});
}
});
I load the contenteditable script on the page in a separate Ajax, mainly because it's a little hefty in size, and since it loads near the bottom of the page I just force it to be the last thing to load.
Input tags and textareas load on the page normally, though.
What I've discovered is that when I click on an input element, #local_element hides and shows as expected. But clicking on the contenteditable doesn't do anything, and it doesn't show up in the console log that the focus or blur are triggered at all.
But when I moved the above script to the bottom of the Ajax, though, it DID work.
To add to the confusion, I have another script in the header (just below mobile.js) that runs on all devices, and it includes variable names, the Ajax function, etc. This script DOES appear to be running within the Ajax!
Can you guys suggest a reason why this one script isn't running as expected?
Still working within a contenteditable, and I'm manipulating data that's being pasted in.
It seems like I have two ways of doing this, and I would like your advice on which way is going to be faster or overall better... or if you have any other suggestions to make it faster or better.
Option 1, lists "beforepaste" and "paste" separately:
$('#comment')
// this works for IE9, and probably earlier
.on('beforepaste', function(e) {
if (window.clipboardData) {
// there's a hidden contenteditable on the page named "ieClipboard". This puts
// the pasted data there, manipulates it, then copies it back to the original element.
// This is apparently the only way to do this on IE9
if (clp.types.indexOf('text/html') !== -1) type = 'html';
a = editClip(clp.getData('text/' + type));
document.execCommand('insertHTML', false, a);
return;
}
}
else {
a = editClip($(this).html(), 'off');
$(this).html(a);
}
})
The second option is marginally shorter, it seems a little easier to read, and it fixes the worry of the "else" condition being triggered after "beforepaste" was already processed. But I wasn't sure if it would be slower to process since I'm doubling-down on the triggers (ie, forcing a larger function that would have otherwise been skipped).
Which option do you guys think is better?
Going a little further, I have one minor nuisance... in section for IE9, it's always going to put the pasted data at the beginning of the text instead of where the cursor was positioned. Any suggestion on how to correct that?
I have this script that makes the height of an element with an [data-resize] attribute grow and shrink so that it always fits the content:
var maxHt = 100;
$.each($('[data-resize]'), function(e) {
var offset = this.offsetHeight - this.clientHeight;
$(this).on('keyup', function() {
if (this.scrollHeight < maxHt)
$(this).css('height', 'auto') // not sure why I have to do it like this, but I do...
.css('height', this.scrollHeight + offset);
else
$(this).css({ 'height' : maxHt + 'px',
'overflow-y' : 'scroll' });
})
.removeAttr('data-resize');
});
If I remove lines 7, 11, 12, and 13 then it works perfectly to make the element grow and shrink to infinity. But I don't want it to grow to infinity, I want it to stop growing at a certain point so that the user only has the most relevant content in view.
So the above works OK, except that it doesn't shrink back to the original when they backspace or delete. Which makes sense, because after it has grown past maxHt then this.scrollHeight is not going to be less than maxHt.
I also tried $(this).height(), this.clientHeight, and this.offsetHeight, but none of them worked correctly.
I've discovered that the non-standard CSS to make something unselectable doesn't work in IE9:
.unselectable, [data-em] {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
When a user inserts an emoji to my contenteditable, I don't want them to be able to click on it and drag to change the size... backspacing to delete it is necessary, I just don't want them to mess with the size.
I know that I can apply the attribute unselectable="on", but I have to do that manually on each emoji. Considering a message board where a thread can have hundreds of replies, and dozens of emojis on each reply, that's just a lot of unnecessary HTML. So I'm hoping to find a jQuery solution.
The image looks like this:
<img src="image.gif" data-em="47" alt="">
The emojis always have the data-em="xx" attribute, so I thought this would work:
but when I click on the emoji it doesn't look like the event is being triggered at all (nothing in the console).
Can you guys suggest what I might be doing wrong? Or any other ideas on how to make it unselectable in IE9?
FWIW, I know that IE9 is an old browser, but I still have a significant amount of traffic using it. IE8 and 7 still show up, too, but they represent less than 0.1% of my traffic so I'm OK with ignoring them.
Inside of a contenteditable, say that the caret is inside of a specific node (in my case, <q data-em="1"></q> ). How can I immediately kick the caret outside of the node, past the ending tag?
I'm using the same loop that Jake helped me build in another thread to find when they're within the Q element:
$('[data-ce]').on('click keydown', function(e) {
var node = getSelection().anchorNode.parentNode;
while (node && node.hasAttribute && !node.hasAttribute('contenteditable')) {
In my case, the <q> element is a CSS sprite for the emojis, but there are times when Firefox and my Android browser will focus inside of the <q></q> tag instead of outside of it, which leads to something like <q data-em="1"><q data-em="2"></q></q>.
I was using a regex to fix it, but then I lose the focus. So instead, I'm hoping to find a way to ensure that the caret is always forced to be outside of the node as soon as it's inserted.
Is there a way to check if a class that's assigned to something is actually defined on the site?
I'm specifically working with content posted into a contenteditable. If they copied from my site then I want to keep the classes, but if they copied from another site and are bringing over classes from that site, then I want to remove them.
I'm not quite sure how to test this for myself, but I'm thinking this might be a rookie question, anyway.
Is it generally faster to test if an element has a class assigned to it before removing it? Or is that just doubling down on the processing time whether it's true or false, in which case it would be faster to just remove it without testing?
if ($('[data-richcont]').hasClass('on'))
$('[data-richcont]').removeClass('on');
And does the same stay true if I use removeClass('on').addClass('off')?
If the question is confusing (it IS 3am while I'm typing), I'm thinking of how a regex like this would be slower because it runs the regex once if it fails, twice if it passes... so you might as well skip the if() and just run it once:
var text_match = /(<div [^>]+>)([\w-]+)<\/div>/gi;
// this runs the same regex twice
if (text_match.test(a))
a = a.replace(text_match, '$2');
// while this runs it once, and it only works if it matches anyway
This is within a contenteditable section, much like the reply field in this forum. When the user has bolded something, I'm changing the class for the "Bold" button to highlight.
I'm pretty sure that the problem is that when I key over to the bolded section manually, $(e.target) becomes equal to "this" instead of to the innermost node.
Is $(e.target) the wrong thing to use here? If not, can you guys suggest how to make it recognize properly when I key over to it?
I find the opposite question a lot, but I haven't found the answer to this one yet! :-)
I'm trying to load a file in to the user's cache, but not actually use it on that page. The logic is, on the first page load I would use PHP's include() to load the CSS inline, then at the bottom of the page I would load the external CSS file to cache it and set a cookie to signify that it has been cached. Then on the second page load I would test for the cookie, and if present I could link to the CSS like normal.
From my tests, this would save about 1.5s on the first page load. And from my experience, the faster the page load the more pages per session I get, so over time this has financial value to me.
I tried using $.get and $.load, but neither of them properly cached it (at least, Google Dev Console shows it loading again on the second page). Is there a more appropriate method?
I'm technically using a separate script for taphold instead of jQuery Mobile, but when I tested with JQM I had the same problem.
I have a page (infinite scroll) with potentially 2000+ elements. I want the user to be able to taphold any one of these elements to run an Ajax script.
What is the proper event to use in order to trigger the taphold?
Here is my code:
function holdClick(id, username) {
$('#list_' + id).on('taphold', function(e) {
alert('worked');
// I tried removing the following 2 lines, but it had no impact on the problem
The problem I'm having is that it doesn't work when I hold the first time, but after I let off and taphold several times it will finally work. I can't figure out if the problem is with the onClick (I also tried using onMouseDown), the script I'm using, the :hover in CSS, or the JQM script.
When I try to use the stable releases of jQuery and jQuery Mobile, I'm having 2 specific problems:
1. The swipeleft feature stops working. No errors in the console, it just doesn't fire. Changing jQuery to 2.2.4 and leaving jQuery Mobile at 1.4.5 does work, though.
2. All on my <input ...> <label ...> elements turn in to blocks instead of inline. The labels still show up inline, but there's an apparent break (and tab) after each <label>. And removing the <label> tags doesn't help, it just puts a break (and tab) after the <input>
Even setting the CSS to:
input, label { display: inline }
has no impact on the glitch. The only way I've found to fix this one is by changing Mobile back to 1.2.1.
So to make both errors work correctly, I'm forced to use jQuery 2.2.4 and jQuery Mobile 1.2.1.
Are these known bugs with workarounds, or do I just need to stick with older versions and wait for the next releases?