Detecting :first-letter by javascript - javascript

I need to know if an element is styled with a :first-letter style, and it should be a general solution so I won't depend on class names or special style attributes. Is there any way? Example:
<p class="initial">First</p>
<p>Second</p>
.initial:first-letter {
float: left;
font-size: 1.5em;
font-weight: bold;
}
$('p').click(function(){
// how to determine if :first-letter is applied to current paragraph?
});

If your CSS is self-hosted, you can:
Get a list of all CSS blocks
Filter out CSS blocks which do not contain :first-letter in the block's selector
Iterate over the list of remaining CSS blocks, and run matchesSelector() with the target element as a receiver and the current CSS block's selector as the argument.
If matchesSelector() returns true, then the current CSS block's rules affect the target element's first letter.
Otherwise move on to the next CSS block in the list
If the CSS isn't self-hosted and the CDN doesn't send CORS headers, then you cannot read the CSS file source
due to privacy issues and this cannot be done.
I have also left out figuring out rule-cascading from the algorithm. Another bump in the road is to figure out what pseudo-selectors affect matchesSelector in a false way.
Like consider:
p.webkitMatchesSelector("p:first-letter") //false
So one would have to remove pseudos like :first-letter from the string before attempting to match as these are irrelevant (but pseudos like :nth-child are not because they truly affect matching).
Demo http://jsfiddle.net/PBuzb/5/ (keep in mind the problems I mentioned are not handled really well here) (The base of code originally by Crush)
Why is it not allowed to read CSS source in cross-origin situation?
The reason you can only show images, run css/js etc.. from other domains BUT absolutely not access their data in any way is privacy.
The case is easiest to make for images. Let's say I am logged in to facebook, and facebook uses url for private photo like
http://facebook.com/myprofile.png. Now I go to evil.com, and evil.com can load the image because I am logged in to facebook,
the facebook will give them that image. Normally they cannot access the image or steal it in anyway, but if we enabled
cross-origin data access, they could now access my private photo and spread it out.
The same can happen in CSS, there could be user-specific CSS generated by the facebook server that contains user ids of my private
friends. They are not so private anymore if any website I can go to can just link to that css and start reading it.
And yes, the main issue is how browsers send cookies with cross-origin request, if the browser didn't send cookies when requesting
facebook images/css from evil.com, then facebook could not respond with user-specific css or my private photos because the cookies
were necessary to recognize me.
Now imagine if browsers didn't send cookies. Evil.com could still access any intranet data this way because my browser has access to the intranet. Being able to show http://intranet/Myboss.jpg as an image on evil.com website is not a problem, but Evil.com being able to read the image data and thus be able to copy and spread it is a problem.

You can iterate over the cssRules, build an array of all the ::first-letter rules, and then check if the element has one of these rules.
Working DEMO (Tested in Chrome only)
(function() {
var firstLetterRules = [];
var loadRules = function() {
var stylesheets = document.styleSheets;
for (var i = 0; i < stylesheets.length; i++) {
var stylesheet = stylesheets[i];
var rules = stylesheet.cssRules;
for (var k = 0; k < rules.length; k++) {
var rule = rules[k];
if (rule.selectorText.indexOf("::first-letter") !== -1) {
//It is a ::first-letter selector. Add the rule to a list of ::first-letter rules.
firstLetterRules.push(rule.selectorText.toUpperCase());
}
}
}
};
window.hasFirstLetterStyle = function(element) {
var fullSelector = element.nodeName;
if (element.className != '')
fullSelector += '.' + element.className;
fullSelector = fullSelector.toUpperCase() + "::FIRST-LETTER";
for (var i = 0; i < firstLetterRules.length; i++) {
if (fullSelector == firstLetterRules[i])
return true;
}
return false;
};
loadRules();
})();
var element = document.getElementById("init");
if (hasFirstLetterStyle(element)) {
console.log("Element has a first-letter style rule.");
}

You cannot.
Pseudo-selectors and their styles are not accessible from your JS code.
The closest you can do is check whether the element has the relevant class that would trigger the first-letter styles, and make the assumption in your JS code that if the class is there, then the first-letter style must have been applied.
There really isn't any other way, short of parsing your way through the whole CSS file manually.
This also applies to other pseudo-selectors and pseudo-elements (you'll find a number of similar questions around here asking similar questions about :before and :after, with similar answers)

Related

Starting from random pages in Google Web Designer

I've been using Google Web Designer for a few months and I have a question. I don't know if it's possible to do in GWD:
I want the index.html file to load a different random page, choosing between 3 pages. When you hit reload, it should load another random page, and so on. The pages don't need to appear in order. I'm trying to find out how this can be done but I had no success so far.
This can be accomplished with a custom JavaScript event handler.
The <gwd-doubleclick> element fires an adinitialized event before any content is displayed, which we can use to make sure our changes are applied before the user sees the first page. It also provides a .goToPage(n) method which we can use to switch pages. (goToPage has additional arguments that can be used to control animation between pages, but we can ignore those because we want the default behaviour of instantly jumping.)
Start by adding a new event handler.
target: document.body
event: Google Ad: Ad Initialized
action: Custom: Add Custom Action
configuration: a name of your choice (such as gwd.goToRandomPage), for the following code:
var pages = 3; // adjust as appropriate
var targetPage = Math.floor(Math.random() * pages);
event.target.goToPage(targetPage);
In code view you can see that this produces something like the following:
// This script block is auto-generated. Please do not edit!
gwd.actions.events.registerEventHandlers = function(event) {
gwd.actions.events.addHandler('document.body', 'adinitialized', gwd.goToRandomPage, false);
};
gwd.actions.events.deregisterEventHandlers = function(event) {
gwd.actions.events.removeHandler('document.body', 'adinitialized', gwd.goToRandomPage, false);
};
You could choose to skip the GWD UI and use the standard JavaScript event handling APIs to accomplish the same thing, with something along the lines of:
document.body.addEventListener('adinitialized', function() {
var pages = 3; // adjust as appropriate
var targetPage = Math.floor(Math.random() * pages);
event.target.goToPage(targetPage);
});
However, you probably want to avoid this in general, because it will prevent GWD from handling things like element renaming automatically.
If you'd like to jump to one of a specific set of pages, instead of selecting from all pages, you could use an array of page IDs instead.
var pageIds = ['page1_1', 'page1_2'];
var targetPage = pageIds[Math.floor(Math.random() * pageIds.length)];
event.target.goToPage(targetPage);
For future reference, you can find most of the component APIs described in the documentation. Questions about GWD that do not involve code or are otherwise unsuitable for Stack Overflow should be asked on the GWD support forum instead.

Refreshing elements inside ul that find place in a iframe

I have a div that contains a iframe from another website. In that website you can find a UL and its updates every time user adds a feedback. This is the ul:
Is it any way I can refresh only this ul every x seconds so I get the feedbacks in realtime?
Thanks
No if they are in a different domains. Using Javascript you can't get information from another website due the Same Origin Police. It's a security restriction that browsers implements and you can't bypass.
Same Origin Police policy permits scripts running on pages originating
from the same site – a combination of scheme, hostname, and port
number – to access each other's DOM with no specific restrictions, but
prevents access to DOM on different sites.
If you want to keep updated from another website you may need use a server side language (JAVA, PHP, NodeJS, etc...) to make a request, parse the return HTML from other website and find the information you need.
EDIT:
If you just need update the iframe every X seconds you can use setInterval:
var refreshFrame= function () {
var iFrames = document.getElementsByClassName("yourClassName");
for(var i = 0; i < iFrames.length; i++) {
if(iFrames[i].className === "yourClassName") {
iFrames[i].src = iFrames[i].src;
}
}
}
window.setInterval(refreshFrame, 3000); // Time in ms
look this FIDDLE

For all links, add css to switch color of link based off Post Type using JS or PHP - Wordpress

I'm not sure what route to start down or what would be the appropriate way to do what I'm trying to accomplish here. Whether it's possible to do in PHP, or how to do it in JS, any help is greatly appreciated.
For each link found on a page, (possibly found within widgets,theme's template pages, forums, etc.), how do I search and find out the post_type and then append a specific link color for that particular type?
So for example:
For a list of recent posts in a sidebar widget
(here is the best way I can describe the code intentions):
For each post_type, dynamically set the following
'post'= color:black,
'project' = color:dark blue,
'topics' = color:dark green,
and so on.
Additionally, if there is a link to another post anywhere else in the site, such as in another post's body content or even a forum topic, I need to append a class to that link. Then my CSS can be something along the lines of
.forum-post-link{color: #006400;}
.project-post-link{color: #00008B;}
.standard-post-link{color:#000;}
Here's a solution that should work off the shelf. You may need to adjust the selector a bit to avoid main site navigation links.
An anchor <a> with an href automatically has numerous properties such as hostname , pathname , origin etc that relate to various parts of the url. Following uses these properties to isolate links that are external ( not same domain ) and also find the home page links.
It should be fairly easy to adapt to live site based on comments within as well as extend for more than the 3 main routes mentioned in question.
/* set according to site domain */
var siteHost = "myurl.com";
var linkClasses = {
/* adjust string values as classes to suit css rules, keys match term to look for in url */
post: 'post',
forum: 'forum',
project: 'project'
}
$('a').each(function () {
var host = this.hostname; /* returns domain.com */
if (host !== siteHost) {
return; /* not a local link, quit here */
}
var newClass = '';
var path = this.pathname; /* returns eveything after http://myurl.com */
if (path && path !== '/') {
/* we only want to look at first part of path*/
var mainPath = path.split('/')[1];
/* now check all the various terms in linkClasses object */
$.each(linkClasses, function (key, value) {
if (mainPath.indexOf(key) > -1) {
newClass = linkClasses[key];
}
});
$(this).addClass(newClass);
} else {
/* is home page link */
$(this).addClass('home'); /* to test home page link finding ability */
}
});
DEMO

How can I use localStorage to remember which classes were set on an element

I'm going to use Mousetrap so when a user presses Alt+L it uses jQuery and adds the class light to body tag, I'd also like it to remove the class once Alt+L is pressed.
How can I add localstorage to remember if there is class light?
I won't provide the code because it's so simple that I don't need to. Instead, I will provide you guidance to use documentation which will give you answers to the api's you request information about.
localStorage is incredibly straight forward. It's a simple key/value store.
https://developer.mozilla.org/en-US/docs/DOM/Storage
The Mozilla Developer Network will provide you information on what api's do and how they work (with working examples).
I'd also like to mention, that there is likely questions about localStorage on StackOverflow already. Here is a post on StackOverflow - Modify localstorage?
Welcome.
To match the OP's REAL question, "How can I use localStorage to remember which classes were set on an element".
var $body = $("body");
// On ALT+L event
if ($body.hasClass("light")) {
$body.addClass("light");
window.localStorage.hasLightClass = true;
} else {
window.localStorage.hasLightClass = false;
$body.removeClass("light");
}
// On page load
var hasClass = window.localStorage.hasLightClass || false;
if (JSON.parse(hasClass)) {
$body.addClass("light");
}

The definitive best way to preload images using JavaScript/jQuery?

I'm fully aware that this question has been asked and answered everywhere, both on SO and off. However, every time there seems to be a different answer, e.g. this, this and that.
I don't care whether it's using jQuery or not - what's important is that it works, and is cross-browser.]
So, what is the best way to preload images?
Unfortunately, that depends on your purpose.
If you plan to use the images for purposes of style, your best bet is to use sprites.
http://www.alistapart.com/articles/sprites2
However, if you plan to use the images in <img> tags, then you'll want to pre-load them with
function preload(sources)
{
var images = [];
for (i = 0, length = sources.length; i < length; ++i) {
images[i] = new Image();
images[i].src = sources[i];
}
}
(modified source taken from What is the best way to preload multiple images in JavaScript?)
using new Image() does not involve the expense of using DOM methods but a new request for the image specified will be added to the queue. As the image is, at this point, not actually added to the page, there is no re-rendering involved. I would recommend, however, adding this to the end of your page (as all of your scripts should be, when possible) to prevent it from holding up more critical elements.
Edit: Edited to reflect comment quite correctly pointing out that separate Image objects are required to work properly. Thanks, and my bad for not checking it more closely.
Edit2: edited to make the reusability more obvious
Edit 3 (3 years later):
Due to changes in how browsers handle non-visible images (display:none or, as in this answer, never appended to the document) a new approach to pre-loading is preferred.
You can use an Ajax request to force early retrieval of images. Using jQuery, for example:
jQuery.get(source);
Or in the context of our previous example, you could do:
function preload(sources)
{
jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
Note that this doesn't apply to the case of sprites which are fine as-is. This is just for things like photo galleries or sliders/carousels with images where the images aren't loading because they are not visible initially.
Also note that this method does not work for IE (ajax is normally not used to retrieve image data).
Spriting
As others have mentioned, spriting works quite well for a variety of reasons, however, it's not as good as its made out to be.
On the upside, you end up making only one HTTP request for your images. YMMV though.
On the down side you are loading everything in one HTTP request. Since most current browsers are limited to 2 concurrent connections the image request can block other requests. Hence YMMV and something like your menu background might not render for a bit.
Multiple images share the same color palette so there is some saving but this is not always the case and even so it's negligible.
Compression is improved because there is more shared data between images.
Dealing with irregular shapes is tricky though. Combining all new images into the new one is another annoyance.
Low jack approach using <img> tags
If you are looking for the most definitive solution then you should go with the low-jack approach which I still prefer. Create <img> links to the images at the end of your document and set the width and height to 1x1 pixel and additionally put them in a hidden div. If they are at the end of the page, they will be loaded after other content.
As of January 2013 none of the methods described here worked for me, so here's what did instead, tested and working with Chrome 25 and Firefox 18. Uses jQuery and this plugin to work around the load event quirks:
function preload(sources, callback) {
if(sources.length) {
var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);
$.each(sources, function(i,source) {
$("<img/>").attr("src", source).appendTo(preloaderDiv);
if(i == (sources.length-1)) {
$(preloaderDiv).imagesLoaded(function() {
$(this).remove();
if(callback) callback();
});
}
});
} else {
if(callback) callback();
}
}
Usage:
preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() {
console.log("done");
});
Note that you'll get mixed results if the cache is disabled, which it is by default on Chrome when the developer tools are open, so keep that in mind.
In my opinion, using Multipart XMLHttpRequest introduced by some libraries will be a preferred solution in the following years. However IE < v8, still don't support data:uri (even IE8 has limited support, allowing up to 32kb). Here is an implementation of parallel image preloading - http://code.google.com/p/core-framework/wiki/ImagePreloading , it's bundled in framework but still worth taking a look.
This was from a long time ago so I dont know how many people are still interested in preloading an image.
My solution was even more simple.
I just used CSS.
#hidden_preload {
height: 1px;
left: -20000px;
position: absolute;
top: -20000px;
width: 1px;
}
Here goes my simple solution with a fade in on the image after it is loaded.
function preloadImage(_imgUrl, _container){
var image = new Image();
image.src = _imgUrl;
image.onload = function(){
$(_container).fadeTo(500, 1);
};
}
For my use case I had a carousel with full screen images that I wanted to preload. However since the images display in order, and could take a few seconds each to load, it's important that I load them in order, sequentially.
For this I used the async library's waterfall() method (https://github.com/caolan/async#waterfall)
// Preload all images in the carousel in order.
image_preload_array = [];
$('div.carousel-image').each(function(){
var url = $(this).data('image-url');
image_preload_array.push(function(callback) {
var $img = $('<img/>')
$img.load(function() {
callback(null);
})[0].src = url;
});
});
async.waterfall(image_preload_array);
This works by creating an array of functions, each function is passed the parameter callback() which it needs to execute in order to call the next function in the array. The first parameter of callback() is an error message, which will exit the sequence if a non-null value is provided, so we pass null each time.
See this:
http://www.mattfarina.com/2007/02/01/preloading_images_with_jquery
Related question on SO:
jquery hidden preload

Categories

Resources