I'm using a WordPress theme that only has about 10 lines of jQuery, yet it's using the 90kb jQuery file. I want to change this jQuery code to Javascript, but I'm not very good at Javascript:
jQuery('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a').live("click", function () {
$href = jQuery(this).attr('href');
$contentArea.fadeTo('fast', 0.2).load($href + ' #main-area', function () {
$contentArea.fadeTo('fast', 1);
});
return false;
});
var $tabbed_area = jQuery('div#tabbed');
if ($tabbed_area.length) {
$tabbed_area.tabs({
fx: {
opacity: 'toggle'
}
});
};
Thanks in advance!
Personally I'd persist with jQuery. Although there is "only about 10 lines jQuery" what it is doing is quite substantial. By the time you have recreated a lot of what jQuery is providing you here you will have a fairly decent slab of javaScript to debug and maintain. That is the beauty of jQuery, to quote their tag line "write less, do more" Remember with jQuery you are eliminating a lot of annoying cross browser quirks.
Edit: See tbranyen's answer for a practical example of why jQuery is worth it
Use a CDN version of jQuery, like Google's and you will be using jQuery that your uses may already have cached and therefore does not have to be downloaded again. jQuery UI can also be served in the same way. See this article: http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/
EDIT
Reading your question further "I'm not very good at javaScript" is all the more reason to stick with jQuery. Let it do all the heaving lifting for you. HOWEVER don't use jQuery as an excuse not to learn more about javaScript, the more you learn about javaScript the more you will be able to get out of jQuery.
My solution is fragmented, its not complete, and I do not expect points for this answer. This was me taking a stab at replicating jQuery's code in vanilla JS, purely as scientific justice to your question. I consider myself good at JavaScript, but even I know my limitations and time constraints. I only have one life on this planet and its honestly not worth my time to write out a tabs plugin and animation for your Wordpress site.
Just take a look at the code difference. If you're really scared about people downloading, you should ask yourself what makes your site so much different than the thousands/millions? of other sites that are visited by millions of people?
Writing this stuff is tedious, that's why if I have to do these things, I use jQuery. However, lets say you don't care about older browser support. You didn't mention that, I have a solution at the very bottom that does more, but WILL not work with older browsers or work period for that matter.
The original
Very little code to do immensely complicated stuff.
jQuery('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a').live("click", function () {
$href = jQuery(this).attr('href');
$contentArea.fadeTo('fast', 0.2).load($href + ' #main-area', function () {
$contentArea.fadeTo('fast', 1);
});
return false;
});
Attempting to write from scratch
// Not even close to finished solution
(function(window, document) {
var tabbed = document.getElementById('tabbed');
// Semi-normalized event handling, not even a fraction as good as jQuery's
function attachEvent(node, type, callback) {
if(node.attachEvent) {
return node.attachEvent('on'+type, function() {
callback.apply(window.event.target, arguments);
});
}
return node.addEventListener(type, function(e) {
callback.apply(e.target, arguments);
}, true);
}
// Semi-delegation again, not even a fraction of what jQuery offers
attachEvent(document, 'click', function(e) {
var href = this.href;
var body = document.body;
var elements = [];
var slice = [].slice;
var concat = elements.concat;
// This is just the start of what it would take to emulate what jQuery is doing to match all those items
// Without a reliable selector engine like querySelectorAll (not even that reliable) you'd need to match.
elements = concat(slice.call(body.getElementById('main-tabbed-area').getElementsByTagName('a')));
elements = concat(slice.call(body.getElementsByTagName('...');
// Not even going to attempt fading
// jQuery again does all this
});
if(tabbed && tabbed.tagName === 'div') {
// No idea what tabs is? A plugin? Good luck!
}
})(this, this.document);
Code is slightly more modern... but still jeesh look at all that code
function xhr(url, callback) {
var request = new window.XMLHttpRequest();
request.open('GET', url, true);
request.onreadystatechange = function(e) {
if(e.readyState === 4) {
callback(e.responseXML);
}
};
request.send(null);
}
// No idea what contentArea is
var contentArea = ...???;
(function(window, document) {
var tabbed = document.getElementsById('tabbed');
document.addEventListener('click', function(e) {
var href;
var elements = document.querySelectorAll('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a');
var match = false;
elements.forEach(function(element) {
if(this === element) {
match = true;
}
});
if(match) {
href = e.target.href;
// Some CSS3 class that does a fade out
contentArea.classList.add('fadeOut');
xhr(href, function(data) {
var data = data.getElementById('main-area').innerHTML;
contentArea.innerHTML = data;
contentArea.classList.remove('fadeOut');
// Some CSS3 class that does a fade in
contentArea.classList.add('fadeIn');
});
return false;
}
}, true);
if(tabbed && tabbed.tagName === 'div') {
// Still no idea what tabs is? A plugin? Good luck!
}
})(this, this.document);
Related
there is a page with some basic HTML that I cannot touch that looks like this:
<a class="continue-shopping" href="https://someURL">Continue shopping</a>
what I want to do is send the user to a different link when they click on the someURL text link. the user can come to a page containing this html from many other pages.
i have tried many hours but cannot get my js to recognize a click event for a class associated with hyperlinked text. i could really use some help here. this is the js code i wrote which does not work
window.onload = function() {
prepEventHandler();
}
function prepEventHandler () {
var myClass = document.getElementsByClassName("continue-shopping");
myClass[0].onclick=window.open(document.referrer,"_self");
/* which make my pages go haywire OR THIS -- which also does not work */
myClass[0].addEventListener("click", function() {
window.open(document.referrer,"_self");
}
)
}
It just keeps ignoring the second function, and I am sure I am doing some really basic that is wrong. Again, thanks for any help!
Apart from preventDefault() you could also use return false
window.onload = function () {
var myClass = document.querySelector(".continue-shopping")
.onclick = function () {
window.location.href = "http://elsewere.com";
return false;
}
}
this code should work but it no longer does and i do not know why any hint much appreciated - there seems to be some problem with myClass[0]
window.onload = function() {
var myClass = document.getElementsByClassName('continue-shopping');
myClass[0].addEventListener("click", function(e) {
e.preventDefault();
window.location.href = document.referrer;
});
}
First Question here, too! Yay! Just moved this from AskUbuntu.
I am just about to finish a little private project for gaining some experience where i try to change the app layout so it works as a normal website (on Jimdo, so it was quite of a challenge first) without much JavaScript required but is fully functional on mobile view.
Since Jimdo serves naturally only the actual site, I had to implement an
if (activeTab.getAttribute('jimdo-target') != null)
location.href = activeTab.getAttribute('jimdo-target');
redirect into the __doSelectTab() function in tabs.js . (In js I took the values from the jimdo menu string to build the TABS menu with this link attribute)
Now everything works fine exept at page load the first tab is selected. I got it to set the .active and .inactive classes right easily, but it is not shifted to the left.
So my next idea is to let it initialize as always and then send a command to change to the current tab.
Do you have any idea how to manage this? I couldn't because of the this.thisandthat element I apparently don't really understand...
Most of you answering have the toolkit and the whole code, but I am listing the select function part of the tabs.js:
__doSelectTab: function(tabElement, forcedSelection) {
if ( ! tabElement)
return;
if (tabElement.getAttribute("data-role") !== 'tabitem')
return;
if (forcedSelection ||
(Array.prototype.slice.call(tabElement.classList)).indexOf('inactive') > -1) {
window.clearTimeout(t2);
activeTab = this._tabs.querySelector('[data-role="tabitem"].active');
offsetX = this.offsetLeft;
this._tabs.style['-webkit-transition-duration'] = '.3s';
this._tabs.style.webkitTransform = 'translate3d(-' + offsetX + 'px,0,0)';
this.__updateActiveTab(tabElement, activeTab);
if (activeTab.getAttribute('jimdo-target') != null)
location.href = activeTab.getAttribute('jimdo-target');
[].forEach.call(this._tabs.querySelectorAll('[data-role="tabitem"]:not(.active)'), function (e) {
e.classList.remove('inactive');
});
var targetPageId = tabElement.getAttribute('data-page');
this.activate(targetPageId);
this.__dispatchTabChangedEvent(targetPageId);
} else {
[].forEach.call(this._tabs.querySelectorAll('[data-role="tabitem"]:not(.active)'), function (el) {
el.classList.toggle('inactive');
});
var self = this;
t2 = window.setTimeout(function () {
var nonActiveTabs = self._tabs.querySelectorAll('[data-role="tabitem"]:not(.active)');
[].forEach.call(nonActiveTabs, function (el) {
el.classList.toggle('inactive');
});
}, 3000);
}
},
...and my app.js hasn't anything special:
var UI = new UbuntuUI();
document.addEventListener('deviceready', function() { console.log('device ready') }, true);
$(document).ready(function () {
recreate_jimdo_nav();
UI.init();
});
So meanwhile found a simple workaround, however I'd still like to know if there is another way. Eventually I noticed the __doSelectTab() function is the one that executes the click, so it does nothing but to show the other tab names when they are hidden first. so I added the global value
var jnavinitialized = false;
at the beginning of the tabs.js and run
var t = this;
setTimeout(function(){t.__doSelectTab(t._tabs.querySelector('[data-role="tabitem"].jnav-current'))}, 0);
setTimeout(function(){t.__doSelectTab(t._tabs.querySelector('[data-role="tabitem"].jnav-current'))}, 1);
setTimeout(function(){jnavinitialized = true;}, 10);
at the top of the __setupInitialTabVisibility() function. Then I changed the location.href command to
if (activeTab.getAttribute('jimdo-target') != null && jnavinitialized)
location.href = activeTab.getAttribute('jimdo-target');
And it works. But originally I searched for a way to change the tab on command, not to run the command for selecting twice. So if you know a better or cleaner way, you are welcome!
I'm a rookie when it comes to programming, so I really need your help here. I need to change some code to fulfil my needs and I can't seem to do it in a proper way. What I need right now, is to take this script and make it work when the $(window).width > 480 . Also, I need this script to run every time the user resizes the window.
I apologise for my silly question, but I'm just starting to learn the basics about Javascript and Jquery, and I can't seem to find the answer to this question this time.
Here is the code
$(window).load(function(){
(function($) {
$.fn.eqHeights = function() {
var el = $(this);
if (el.length > 0 && !el.data('eqHeights')) {
$(window).bind('resize.eqHeights', function() {
el.eqHeights();
});
el.data('eqHeights', true);
}
return el.each(function() {
var curHighest = 0;
$(this).children().each(function() {
var el = $(this),
elHeight = el.height('auto').height();
if (elHeight > curHighest) {
curHighest = elHeight;
}
}).height(curHighest);
});
};
$('.articles_container').eqHeights();
}(jQuery));
});
The window has an .innerWidth property which I presume is still accessible through jQuery. so your code might be something like this:
$(window).resize(function() {
if($(window).innerWidth < 480) return;
$('.articles_container').eqHeights();
})
To execute it on window resized, do this:
$(window).resize(function() {
$('.articles_container').eqHeights();
}
Also, if you want to execute javascript upon media queries events, then use the sweet enquire.js javascript library.
I'm developing a simple gadget for Windows 7 as a learning exercise.
I read in this article (under the subtopic Gadgets and Script) that to initialize the gadget, you should use document.onreadystatechange instead of events such as onLOad. I've seen it in the example project code I've looked through as well. This is what I came up with for my project.
document.onreadystatechange = function()
{
if(document.readyState == "complete")
{
System.Gadget.settingsUI = "settings.html"; //this line enables the settings UI
System.Gadget.onSettingsClosed = settingsClosed;
}
}
However when I use this snippet in my work, it doesn't work. The Options button in the gadget doesn't show up. If I use onLoad, it works. I have installed 2 gadgets. Each of them use these 2 methods. One use onLoad and the other use document.onreadystatechange. And both of them works!
Now I'm confused why it doesn't work with my gadget. Is there any important part I'm overlooking?
try something along these lines,
move your onsettingsclosed to a different event and call the function with it
document.onreadystatechange = function()
{
if(document.readyState=="complete")
{
var searchTags = System.Gadget.Settings.read("searchTags");
if(searchTags != "")
{
searchBox.value = searchTags;
}
}
}
System.Gadget.onSettingsClosing = function(event)
{
if (event.closeAction == event.Action.commit)
{
var searchTags = searchBox.value;
if(searchTags != "")
{
System.Gadget.Settings.write("searchTags", searchTags);
}
event.cancel = false;
}
}
We're currently not using any serious client side framework besides jQuery (and jQuery.ui + validation + form wizard plugins).
A problem that surfaces a few times in our code is this:
We have a button that initiates an Ajax call to the server.
While the call is taking place, we display a "loading" icon with some text
If the server returns a result too quickly (e.g. < 200 ms), we "sleep" for 200 millis (using setTimeout()), to prevent flickering of the waiting icon & text.
After max(the call returns, a minimal timeout), we clear the loading icon & text.
We then either display an error text, if there was some problem in the ajax call (the server doesn't return 500, but a custom json that has an "error message" property. In fact, sometimes we have such a property in the response per form field ... and we then match errors to form fields ... but I digress).
In case of success, we do ... something (depends on the situation).
I'm trying to minimize code reuse, and either write or reuse a pattern / piece of code / framework that does this. While I probably won't start using an entire new heavy-duty framework just for this use case, I would still like to know what my options are ... perhaps such a client-side framework would be good for other things as well. If there's a lightweight framework that doesn't require me to turn all my code upside down, and I could use just on specific cases, then we might actually use it instead of reinventing the wheel.
I just recently heard about Ember.js - is it a good fit for solving this problem? How would you solve it?
$(function(){
var buttonSelector = "#button";
$('body').on({'click': function(evt){
var $button = $(this);
$button.toggleClass('loading');
var time = new Date();
$.get('some/ajax').then(function(data,text,jqXhr){
// typical guess at load work
$button.empty();
$(data).wrap($button);
}).fail(function(data,text,jqXhr){
alert("failed");
}).done(function(data,text,jqXhr){
var elapsed = new Date();
if((elapsed - time) < 200){
alert("to short, wait");
}
$button.toggleClass('loading');
});
}},buttonSelector,null);
});
Just wrap the $.ajax in your own function. that way you can implement your own queing etc. I would suggest to do a jquery component for this. It can get pretty powerful, for example you can also pass http headers etc.
Regarding frameworks it depends on your requirements.
For example, you may consider Kendo UI, it has good framework for creating data sources:
http://demos.kendoui.com/web/datasource/index.html.
Working Sample Code (well, almost)
I was going for something along the lines of #DefyGravity's answer anyway - his idea is good, but is still pseudo-code/not fully complete. Here is my working code (almost working demo, up to the Ajax URL itself, and UI tweaks)
The code & usage example:
jQuery.fn.disable = function() {
$(this).attr("disabled", "disabled");
$(this).removeClass("enabled");
// Special handling of jquery-ui buttons: http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jquery-ui-dialog
$(this).filter("button").button({disabled: true});
};
jQuery.fn.enable = function() {
$(this).removeAttr("disabled");
$(this).addClass("enabled");
// Special handling of jquery-ui buttons: http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jquery-ui-dialog
$(this).filter("button").button({disabled: false});
};
function AjaxCallbackWaiter(ajaxUrl, button, notificationArea, loadingMessage, errorMessage, inSuccessHandler, inFailureHandler) {
// Every request that takes less than this, will be intentionally delayed to prevent a flickering effect
// http://ripper234.com/p/sometimes-a-little-sleep-is-ok/
var minimalRequestTime = 800;
var loadingIconUrl = 'http://loadinfo.net/images/preview/11_cyrcle_one_24.gif?1200916238';
var loadingImageContent = $("<img class='loading-image small' src='" + loadingIconUrl + "'/><span class='loading-text'>" + loadingMessage + "</span>");
var errorContentTemplate = $("<span class='error ajax-errors'></span>");
var requestSentTime = null;
button.click(clickHandler);
function displayLoadingMessage() {
clearNotificationArea();
notificationArea.html(loadingImageContent);
}
function clearNotificationArea() {
notificationArea.html("");
}
function displayError(message) {
var errorContent = errorContentTemplate.clone(errorContentTemplate).html(message);
notificationArea.html(errorContent);
}
function ajaxHandler(result) {
var requestReceivedTime = new Date().getTime();
var timeElapsed = requestReceivedTime - requestSentTime;
// Reset requestSentTime, preparing it for the next request
requestSentTime = null;
var sleepTime = Math.max(0, minimalRequestTime - timeElapsed);
function action() {
clearNotificationArea();
button.enable();
if (result) {
inSuccessHandler();
} else {
displayError(errorMessage);
inFailureHandler();
}
}
if (sleepTime <= 0) {
action();
} else {
setTimeout(action, sleepTime);
}
}
function failureHandler() {
}
function clickHandler(){
if (requestSentTime !== null) {
logError("Bad state, expected null");
}
requestSentTime = new Date().getTime();
displayLoadingMessage();
button.disable();
$.get(ajaxUrl, 'json').then(ajaxHandler, failureHandler);
}
}
// Usage:
var ajaxUrl = 'FILL IN YOUR OWN URL HERE';
var button = $("#clickme");
var notificationArea = $(".ajax-notification-area");
var waitingMessage = "Doing Stuff";
var errorMessage = "Not Good<br/> Please try again";
$(document).ready(function(){
new AjaxCallbackWaiter(
ajaxUrl,
button,
notificationArea,
waitingMessage,
errorMessage,
function(){
alert("All is well with the world");
},
function(){
alert("Not good - winter is coming");
});
});