I have basically no experience with jQuery, just enough to get by most of the time. However, I recently have been changing some templates around and came across a piece of jQuery that I didn't write, but is throwing an error (Uncaught Error: Syntax error, unrecognized expression: /). I'm not really sure where to start. All I know so far is that I'm fairly certain this piece of code is causing it, and it's choking right at the scrollItems line:
// Cache selectors
var lastId,
topMenu = $(".nav"),
topMenuHeight = topMenu.outerHeight() + 50,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function() {
var item = $($(this).attr("href"));
if (item.length) {
return item;
}
///////////////FANCYBOX
$(".fancybox-media").fancybox({
arrows: true,
padding: 0,
closeBtn: true,
openEffect: 'fade',
closeEffect: 'fade',
prevEffect: 'fade',
nextEffect: 'fade',
helpers: {
media: {},
overlay: {
locked: false
},
buttons: false,
title: {
type: 'inside'
}
},
beforeLoad: function() {
var el, id = $(this.element).data('title-id');
if (id) {
el = $('#' + id);
if (el.length) {
this.title = el.html();
}
}
}
});
});
I have tested the fancybox code separately, and it works, but I thought I'd leave it in to be thorough. There was also some commented out code that I took out. Any help would be very much appreciated!
It's likely that it is this line that is causing the error:
var item = $($(this).attr("href"));
You seem to have a link with href="/" (a link to the start page), so the code will do the same as:
var item = $("/");
jQuery will try to parse the URL as a selector, and you get that exact error message.
Check that the href attribute contains a bookmark and not an URL before you try to use it as a selector:
var href = $(this).attr("href");
if (href.substr(0, 1) == "#") {
var item = $(href);
if (item.length) {
return item;
}
}
Related
I am trying to get Packery.js to work with LazyLoad.js, while having the ability to filter the gallery by tags.
www.temp.fokuspunkt.de
On the initial page load everything works fine:
After clicking throgh the tags and then clicking on the "all" button again, the layout is scrambled, however:
I assume this has to do with the lazy loading, as it can throw off the layout, as described in the documentation here:
https://packery.metafizzy.co/layout.html#imagesloaded
Adding the recommended solution
$grid.imagesLoaded().progress( function() {
$grid.isotope('layout');
});
throws an error, though:
My complete javascript file calling Isotope looks like this, I had tried to copy the above code right beneath the "$(window).on('load',function[...]" function block:
jQuery(function ($) {
var $grid = $('.isotope-list').packery({
layoutMode: 'packery',
filter: '*',
itemSelector: '.isotope-item',
gutter: 0,
});
$(window).on('load',function(){
$grid.packery('layout');
});
imagesLoaded( $grid ).on( 'progress', function() {
pckry.layout();
});
$('.filters li').click(function(){
//css button styling
$('.filters li').removeClass('current');
$(this).addClass('current');
// set isotope filter
var selector = $(this).attr('data-filter');
$grid.isotope({
filter: selector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
});
$grid.packery('layout');
return false;
});
var $win = $(window),
$imgs = $("img"),
$loadVisible = function($els, trigger) {
$els.filter(function () {
var rect = this.getBoundingClientRect();
return rect.top >= 0 && rect.top <= window.innerHeight;
}).trigger(trigger);
}
$grid.packery('on', 'layoutComplete', function () {
$loadVisible($imgs, 'lazylazy');
$grid.packery('layout');
});
$win.on('scroll', function () {
$loadVisible($imgs, 'lazylazy');
});
$win.on('resize', function () {
$grid.packery('layout');
});
$imgs.lazyload({
effect: "fadeIn",
failure_limit: Math.max($imgs.length - 1, 0),
event: 'lazylazy'
});
});
I am certain I am doing something stupid, would anybody be kind enough to tell me what I am doing wrong? Thank you very much in advance!
So, it took a while, but I wanted to return and share my solution. Maybe it helps out somebody else in the future. My main problem was that I used isotope and packery (which is a standalone library), and not isotope and isotope-packery (which is an addon for isotope). I also changed my lazy loading plugin to "lozad", which makes a lot of thins easier.
In the code below you can also find a solution for using multiple filter terms in combination. In my case I use a row of row of radio buttons below the old button row you can see above.
jQuery(function ($) {
// initialize Packery
var $pckry = $('.isotope-list').isotope({
layoutMode: 'packery',
filter: '*',
itemSelector: '.isotope-item',
packery: {
gutter: 0
},
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
});
// layout on first page load, so that the gutter gets set up
$(window).on('load', function () {
$pckry.isotope('layout');
});
// filter items on button click
$('.filters li').click(function () {
$('.filters li').removeClass('current');
$(this).addClass('current');
var combinedFilter = getFilter($('.filters li.current').attr('data-filter')) + getFilter($('input[name="isotope-type-filter"]:checked').val().toLowerCase());
$pckry.isotope({ filter: combinedFilter });
$pckry.isotope('layout');
});
// filter items on radio button change
$('input[name="isotope-type-filter"]').change(function () {
var combinedFilter = getFilter($('.filters li.current').attr('data-filter')) + getFilter($('input[name="isotope-type-filter"]:checked').val().toLowerCase());
$pckry.isotope({ filter: combinedFilter });
$pckry.isotope('layout');
});
function getFilter(buttonGroup) {
var filterValue = '';
if (buttonGroup === '*') {
filterValue = "";
} else {
filterValue = "." + buttonGroup;
}
return filterValue;
};
});
As the title suggests, I'm trying to add a class to the current 'snapped-to' element. With this:
var verticalScroll;
verticalScroll = new IScroll('#wrapper', {
snap: true
});
verticalScroll.on('scrollEnd', function(){
alert(this.currentPage);
});
I get this alert when the scrolling is done:
[object Object]
So I was thinking I could use something like this to add a class:
verticalScroll.on('scrollEnd', function(){
var newPage = this.currentPage;
$(newPage).addClass('current');
});
But no joy. Done lots of searches to try and find the same situation. It must be something fairly simple.
Yeah, it's a little bit tricky. Some time ago I tried to add an "active" class to the link and the page. I ended up with this:
after scroll ended:
myScroll.on('scrollEnd', function () {
addActiveClass();
});
the function:
function addActiveClass() {
// get current page with iScroll
var currentSection = myScroll.currentPage.pageY;
// get current link and page
var activeLink = $('nav a[href="' + currentSection + '"] span');
var activeSection = $('section[class="' + currentSection + '"]');
// remove active class from all links and pages
$('nav a span, section').removeClass('active');
// add active class to current link and page
$(activeLink).addClass('active');
$(activeSection).addClass('active');
}
Only one thing that annoys me, you have to give every section a page number as a class:
<section class="0"> … <section>
<section class="1"> … <section>
<section class="2"> … <section>
Same with links:
But maybe could be added dynamically somehow.
And don't forget option:
snap: 'section'
jsfiddle demo
var workCase;
function loadcase() {
workCase = new IScroll('#work-case', {
mouseWheel: true,
resizeScrollbars: true,
snap: 'section',
interactiveScrollbars: true,
mouseWheelSpeed: 10,
scrollX: true,
scrollY: false,
momentum: true,
snapSpeed: 800,
scrollbars: 'custom',
wheelAction: 'scroll'
});
workCase.on('scrollEnd', function() {
var sectionIndex = Number(this.currentPage.pageY);
var iScrollConteiner = $('#work-case').children()[0];
var dataNumber = $(iScrollConteiner)[0].children[sectionIndex].className;
var activeSection = $('section[class="' + dataNumber + '"]');
$('section').removeClass('active');
$(activeSection).addClass('active');
});
}
I'm writing a jQuery plugin that makes containers (e.g. a div) of a hyperlink clickable.
I would like it for the user to be able to change some basic parameters.
However I must be doing something wrong, because it always uses the default param and not the user defined one.
I try the overrule the cursor.
The fiddle.
The code:
(function($){
$.fn.clickablecontainer = function() {
return this.each(function(options) {
var defaults = {
cursor: 'pointer',
hoverclass: 'hover',
activeclass: 'active'
//ellipsisText: "..."
};
var options = $.extend(defaults, options);
var elem = $(this);
elem.css('cursor', options.cursor);
$('a', elem).css('cursor', options.cursor);
elem.hover(function() {
elem.addClass(options.hoverclass);
}, function() {
elem.removeClass(options.hoverclass);
});
elem.mousedown(function() {
elem.addClass(options.activeclass);
});
$('body').mouseup(function() {
elem.removeClass(options.activeclass);
});
elem.click(function() {
var target = $('a', elem).attr('target');
var href = $('a', elem).attr('href');
switch(target) {
case '':
case '_self':
location.href = href;
break;
case '_blank':
window.open(href);
break;
case '_parent':
parent.location.href = href;
break;
case '_top':
top.location.href = href;
break;
default:
alert('frame');
top.frames[target].location = href;
}
});
});
};
})(jQuery);
$('document').ready(function() {
$('.container div').clickablecontainer({
cursor: 'help'
});
});
Finished product (special thanks to tvanfosson :) ):
fiddle
You have two definitions of options, since you use var to redeclare it. I suspect this results in the options on the right-hand side being an empty object. It would be better to simply use:
options = $.extend({},defaults,options);
This will keep defaults intact, yet allow the values in options to override them, then reassign to the original options variable.
You also need to move the definition of the options to the outer function, otherwise you aren't actually getting any values.
$.fn.clickablecontainer = function(options) {
var defaults = {
cursor: 'pointer',
hoverclass: 'hover',
activeclass: 'active'
//ellipsisText: "..."
};
options = $.extend({},defaults, options);
return this.each(function() {
var elem = $(this);
...
I am working on a "one page" website with a fixed navigation and about 5 different pages inside the one document.
UPDATED WORKING LINK
http://www.coco-works.com/Archive/ LIVE VERSION
I'm having trouble with the active class addition. When you click Keep in Touch or Home, the class is not applied. As you can see from the live version, it's not function properly.
The page works something like this;
And here is the JavaScript;
$(document).ready(function() {
$('body').click(function(event) {
if (event.target.nodeName.toLowerCase() == 'a') {
var op = $(event.target);
var id = op.attr('href');
if (id.indexOf('#') == 0) {
$.scrollTo(id, 1000, {
offset: {
top: 75
},
axis: 'y',
onAfter: function() {
window.location.hash = id.split('#')[1];
}
});
}
return false;
}
});
$.fn.waypoint.defaults.offset = 75;
$('.section h1.page_name').waypoint(function() {
var id = this.id;
var op = $('#navigation a[href = "#' + id + '"]');
if (op.length) {
$("#navigation a").removeClass("active");
op.addClass('active');
}
});
});
I'm not a strong programmer. I've tried to edit it as best as I can and I'm just stuck. Any insight to fixing this would highly be appreciated.
Still looking for an answer, below couldn't fix the problem.
I'm not sure what the waypoints plugin was doing, but I've refactored your code and it is working for me. Note that I took out the call to .waypoints, and changed your $('body').click() handler to be a more specific handler on the navigation link elements. This handler will scroll to each element and then will perform the removal and addition of the class correctly when the scrolling is done:
$(document).ready(function()
{
function highlightNav(navElement){
$("#navigation a").removeClass('active');
navElement.addClass('active');
}
$('#navigation a').click(function(event){
var nav = $(this);
var id = nav.attr('href');
$.scrollTo(id, 1000, {
offset: { top: -75 },
axis: 'y',
onAfter: function(){
highlightNav(nav);
}
});
return false;
});
$(window).scroll(function(){
if($(this).scrollTop() == 0){
highlightNav($("#navigation a[href*='home']"));
}
});
$.fn.waypoint.defaults.offset = 75;
$('.section h1.page_name').waypoint(function() {
var id = this.id;
var op = $('#navigation a[href = "#' + id + '"]');
if (op.length) {
highlightNav(op);
}
});
// Fancybox
$("a.zoom").fancybox({
'overlayShow' : false,
'transitionIn' : 'elastic',
'transitionOut' : 'elastic'
});
$("a.outside_shade").fancybox({
'titlePosition' : 'outside',
'overlayColor' : '#000',
'overlayOpacity' : 0.9
});
$("a.inside_white").fancybox({
'titlePosition' : 'inside'
});
$("a.inside_shade").fancybox({
'titlePosition' : 'over'
});
// validation
$("form").validate();
// nivo slider
$('#slider').nivoSlider();
});
In the html I added a default active class to the first link:
<div id="navigation">
<ul>
<li>Home</li>
<li>Portfolio</li>
<li>Who Are We?</li>
<li>Our Services</li>
<li>Features</li>
<li>Keep in Touch</li>
</ul>
</div>
Also I noticed on the page you have your css defined before the reset.css is called in. That's usually bad practice you might want to make sure reset.css is always the very first css file pulled in. It doesn't appear to have affected the page much but sometimes you'll get weird results doing that.
I made a jsfiddle of the results here: http://jsfiddle.net/RNsFw/2/
the waypoints plugin isn't needed anymore I think. I didn't change the fancybox or validation stuff because i'm not sure what those are doing and it wasn't really part of your issue.
I tested it in firefox and Chrome. Let me know if you have questions :)
http://jsfiddle.net/vCgy8/9/
This removes the dependency on scrollTo, and the waypoints plugin.
$('body').click(function(event)
{
if(event.target.nodeName.toLowerCase() == 'a')
{
var op = $(event.target);
var id = op.attr('href');
if(id.indexOf('#') == 0)
{
destination = $(id).offset().top;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, 1000, function() {
var hash = id.split('#')[1];
window.location.hash = hash;
});
}
return false;
}
});
$(window).scroll(function (event){
makeActive();
});
function makeActive(){
var y = $(this).scrollTop();
if(y!==0){
$('.page_name').each(function(){
var curPos = parseInt($(this).offset().top - y);
if(curPos <= 0){
var op = $('#navigation a[href = "#'+$(this).attr('id')+'"]');
$("#navigation a").removeClass("active");
op.addClass('active');
}
});
}else{
$("#navigation a").removeClass("active");
$("#navigation a:first").addClass('active');
}
}
makeActive();
This may be completely unrelated, but I had a similar problem yesterday - where, in the callback of an event handler, jQuery operations weren't being performed in that scope but if you threw the code into something like:
setTimeout(function() {
$(selector).addClass('foo');
}, 0);
it would work - similar to how $.animate() functions (ish) if you call $(selector).stop().animate() without the queue param being false, eg:
$(selector).stop();
$(selector).animate({ foo }, { no queue:false here });
// ^ fail
$(selector).stop();
setTimeout(function() {
$(selector).animate({ foo }, { no queue:false here either });
}, 0);
// ^ success
The problem, completely unrelated to the above example though similar in behavior/functional hack, turned out to be the method of binding - in my case I had been using $.bind() - but then I refactored this to use $.delegate() ($.live() would work also) and it functioned as expected.
Again, not sure if this related, but figured I'd pass that along just in case. Unsure if it's a bug or just me not properly understanding some of the subtler parts of jQuery.
The problem is not in your js code, but in your css/page layout.
Or maybe the problem is that you are using the waypoint plugin and you might not want to for this particular page. (As you will see you also have trouble hitting the "Home" waypoint again once you have left it, because of the offset you use.)
The thing is, the waypoint plugin won't trigger until the target element you are scrolling to is in the very top of the browser window, with respect to the offset that is. "Keep in touch" will never get to the top unless your browser window is small enough that the "keep in touch" section takes up the entire browser window (minus the offset).
You can see it visualized here:
I have jQuery and the autocomplete plugin setup. Autocomplete works fine and various options I set like width and lookup work okay. But the one thing that does not work is the matchContains option. According to the doc "Whether or not the comparison looks inside (i.e. does "ba" match "foo bar") the search results. Important only if you use caching. Don't mix with autofill." But it is not looking inside the search results. For example, "ba" will not find "foo bar".
<script type="text/javascript" src="styles/prosilver/template/jquery.js"></script>
<script type="text/javascript" src="styles/prosilver/template/jquery.autocomplete.js"></script>
<script type="text/javascript">
// <![CDATA[
/* Zeno */
function translatestyle(text)
{
var val = document.getElementById('query').value;
var lang = '{S_USER_LANG}'.substring(0,2);
var list = "{TRANS_LIST}";
var arr = list.match(val);
if ( arr == null )
{
alert('That is not a valid translation term.');
}
else
{
insert_text('[translate='+lang+']'+val+'[/translate]');
document.forms[form_name].elements[text_name].focus();
}
}
var a2;
jQuery(function() {
var onAutocompleteSelect = function(value, data) {
$('#selection').html('<img src="\/global\/flags\/small\/' + data + '.png" alt="" \/> ' + value);
alert(data);
}
var options = {
serviceUrl: '/projects/autocomplete/service/autocomplete.ashx',
matchContains: true,
width: 300,
delimiter: /(,|;)\s*/,
onSelect: onAutocompleteSelect,
deferRequestBy: 0, //miliseconds
};
a2 = $('#query').autocomplete({
matchContains: true,
width: 300,
delimiter: /(,|;)\s*/,
lookup: "{TRANS_LIST}".split(',')
});
$('#navigation a').each(function() {
$(this).click(function(e) {
var element = $(this).attr('href');
$('html').animate({ scrollTop: $(element).offset().top }, 300, null, function() { document.location = element; });
e.preventDefault();
});
});
});
I'm not familiar with that particular plugin, but you may want to try switching to the JQuery UI Autocomplete library. It's quite good, and does search inside the way you want.
Checkout this website. its got a working example and codes for it.
http://www.ajaxdaddy.com/demo-jquery-autocomplete.html
what i think: what you are missing might be the onfindvalue event and method to handle the event
Example:
source: function (request, response) { // Contains
var searchString = request.term,
items = [];
// OPTIONS
// Search for items with "searchString"...
// Example:
items.push('test 1');
items.push('foo');
items.push('var');
response(items); // Items
}