Best jquery questions in April 2011

Is Javascript/jQuery DOM creation safe until it's added to the document?

28 votes

Please read this statement carefully: let's assume before ANY elements are added to the document all unsafe elements in $dom have been removed. But they were initially created. Ok let's continue....


If a piece of user text is processed and can possiblity be loaded like so:

var comment = 'I\'m a naughty person!!' +
              '<script src="http://blah.com/some_naughty_javascript.js">';
var $dom = $('<div>' + comment + '</div>');

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

For example:

var $dom = $('<script>alert("hi");</script>');

Obviously the message hi does not pop up until it's added to the document. But:

  • Can any tag or anything created in this manner be dangerous?
  • Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

Bounty Edit

So as outlined in the answers below, it seems this method isn't very safe, particularly for one reason:

  • var $dom = $('<img src="blah.jpg"/>') -- this will request for the image straight away, regardless of if the object was added to the document.

This creates a major problem for dealing with HTML ajax requests. For example if we wanted to get the values from the inputs of the form:

$.ajax({
  url: 'test.php',
  success: function(responseHTML) {
    var inputs = $(responseHTML).find('form input');
  }
});

This will involuntarily cause all images to be requested for by the browser.

Bounty is awarded to anyone:

  • Who can provide a nice, safe way of dealing with ajax requests without the above issue.
  • Ideally doesn't provide a regex answer... i.e. what if we wanted to do $(responseHTML).find('img') -- removing image tags with regex can't be an option, so an unobtrusive way would be needed to stop the src from loading, but still have the same attributes, structure, etc.

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

Simply creating an element without appending it to the dom will not cause any script to run since it is purely an object at this point (HtmlScriptElement). When it is actually appended to the dom the script element will be evaluated and ran by the browser. With that being said I suppose it is possible that an extremely crafty person could exploit a bug that is present in some framework or browser you might be using to cause an undesired outcome.

Consider this example:

<p>
    <input type="button" value="Store 'The Script' In Variable" id="store"/>
    <input type="button" value="Append 'The Script' To Dom" id="append"/>
</p>
<br/>
<p>
    <input type="button" value="Does nothing"/>
</p>
<h1>The Script</h1>
<pre id="script">
    $(function(){
        function clickIt(){
            $(this).clone().click(clickIt).appendTo("body");
        }
        $("input[type='button']").val("Now Does Something").click(clickIt);
    });
</pre>

var theScript;

$("#store").click(function() {
    theScript = document.createElement('script');
    var scriptText = document.createTextNode($("#script").text());
    theScript.appendChild(scriptText);
});

$("#append").click(function() {
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(theScript);
});

When you click on store it will create the HtmlScriptElement and store it into a variable. You will notice that nothing is ran even though the object is created. As soon as you click append the script is appended to the dom and immediately evaluated and the buttons do something different.

Code Example on jsfiddle


Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

jQuery sort of does that for you already as it does some internal script eval


From Karl Swedberg post on .append()

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM. ...

You could alter the behavior of jQuery to remove all <script/> and sanitize other elements with inline javascript onclick, mouseover, etc when calling append() however that will only affect jQuery as someone could easily use vanilla javascript to append the <script/> element.

Dom Mutation Events

Dom Level 2 does defined some Dom mutation events to capture elements that are added to the dom one would look towards the event, DOMNodeInserted. However it is fired after the element has already been added. note, per Raynos these are currently deprecated.

DOMNodeInserted Fired when a node has been added as a child of another node. This event is dispatched after the insertion has taken place. The target of this event is the node being inserted. Bubbles: Yes Cancelable: No Context Info: relatedNode holds the parent node

In the end it appears there is no totally stop a <script/> being appended to the dom via some other javascript. (at least not that I can find).

The best way I can suggest is to never ever trust user input as all user input is evil. When you do dom manipulation double check to make sure there are no forbidden tags, be it <script/> or even plain <p/> elements and sanitize all input before it is persisted.

Also as John points out you need to worry about any element that can attach a onclick event or any inline javascript event handler.

Is there a way of testing CSS?

16 votes

I know that this idea has come up before - notably here and here - but no solution seems to have been given. It was largely seen as either a 'nice-to-have-but-impossible' or 'stupid idea'.

My thoughts were using jQuery to calculate computed values and compare them to expected values. For example, I could have <h1>This is a header</h1> and in theory, I should know it's font-size, colour, font-weight, etc. I can use jQuery to check that it is actually that font-size, and if not, return an error.

The advantage of this is that I don't have to sit with a checklist going through each browser - 'Is this header bold? Are these links underlined? Is this column 110px wide?' - every time I make a CSS change.

My question - is that a feasible idea? What are the major problems in implementing something like that? Has anyone done something like that before?

EDIT: Any thoughts on how to actual render the errors are welcome too. I thought of using a JavaScript file in the header of the relevant page and then adding content to the page, kind of like Firebug's on-page version. However, I'm worried that could then affect the rendering of the page. Alternatively, I could log it to the console, but I don't think IE6 has a proper console, and opening every console of every browser for every page-under-test seems a bit annoying as well.

Even if there was a way to do this, I would still feel the need to check manually.

The examples you gave aren't the types of things to typically worry about, but mostly positioning and box-model stuff. If I say h1{color:red} I feel pretty confident that it's going to be red in IE.

Getting the computed values isn't really going to help with finding out how they are rendered, it actually sounds like more work overall than just firing up IEtester. With a bit of experience you quickly learn the types of things you need to check for cross browser compatibility, and with browsers getting better and better, it's becoming less and less of an issue.

One technique that can help: Design in IE. Yes it sucks for sure, but you'll usually find that when you get it working in IE7 and then test in FF, IE8 or IE6 - it's pretty close or the differences are an easy fix compared to testing in say Chrome, and then double checking in IE7. I know that "cross browser" encapsulates more than just IE, but let's not kid ourselves; IE is the problem browser and the most widely used.

In conclusion: If there were a tool for this, it would have to be REALLY AMAZING to keep me from checking in a real browser. I think that's why people are pointing to Selenium as the solution to this.

Formatting events according to start time

15 votes

Hi,

Still working on my planner/calendar application. I'm nearly done, I got some of the harder parts working but I'm stuck at one more difficult part. I want to show my events in a grid according to their start time.

It doesn't show in this picture, but pretend there's a column with hours (8am - 11pm or so) at the left of the 25th. If an event starts at.. say, 1pm, I would like it to show somewhere in the middle of the page. If an event starts at 8:30 am, it should show between 8am and 9am.

events

I guess I could do this with tables, but I was wondering if there's another way. Is this doable with plain html/css, perhaps some Javascript? Any suggestions on what the best way would be to achieve this? If I use a table, I'm still not sure what would be the best way to do this. A cell for every thirty minutes? I have access to the start and end time of each event from my view. An event array (in this example, the 25th) looks like this:

Array

[1] => Array
    (
        [title] => Ethiek
        [description] => Ethiek: Opdracht 1
        [time_start] => 11:30:00
        [time_end] => 12:00:00
    )

[2] => Array
    (
        [title] => Project Management
        [description] => Test: Project Management
        [time_start] => 15:00:00
        [time_end] => 16:00:00
    )

[event_count] => 2

I appreciate any advice you can give me. Thanks a lot!

EDIT: Started a bounty on this because I'm still stuck and I would appreciate some feedback.

UPDATE:

I've been breaking my head over this and I honestly can't figure out the best way to do this. First of all, I think the reason I'm stuck is the way I read out my events from the db/array. This is the code I have to display the events as seen in my screenshot, don't mind my complex arrays:

        foreach($details[0] as $key => $detail)
    {
        echo "<div class='grid'>";
        $header = "<p class='detail_header'>";
        $header .= ucfirst($dates[0][$key]['name']) . ", " . $key . " " . $init['curr_month_name'];
        $header .= "<img src='" . base_url() . "assets/images/create_event.png' alt='Plan iets'></p>";

        echo $header;

        for($i = 1; $i <= $details[0][$key]['event_count']; $i++)
        {
            echo "<div class='event " . $details[0][$key][$i]['type'] . "'>";
                echo "<p class='event_title'>" . $details[0][$key][$i]['title'] . "</p>";
                echo $details[0][$key][$i]['description'];
            echo "</div>";
        }
        echo "</div>";  

    }

It's a bit of a mess, not to mention that I have the same code another time to fix some exceptions. But more importantly.. I feel like those loops don't allow me to make a lot of modifications to it. I tried adding two divs for AM and PM so I could split up the events in before-noon and afternoon blocks, and then just display the time on the event (to avoid having to work with a thousand blocks of 15 minutes). But yeah.. That didn't work out since it would put a couple of 'PM' divs if there is more than one event in the afternoon.

I'm tempted to just leave it like it is for now and just display the start/end time in the event divs.. until I figure out a better way to read them from the array and display them.

Any help/suggestions appreciated. Thanks.

I'm actually also doing this right now. My solution was to go with 960.gs-like divs.

First, I define a series of constants: Start time to display, end time to display, columns per hour, total columns. In my app's case, these variables are configurable by the user.

Second, I query an array of events that I need to deal with. These include a start time and end time, plus the details I want to display. I'll be using jQuery QTip to popup details that hover, so data to populate those is also included in this query.

Now, the 960.gs concept. The basis for a grid is knowing that you have X amount of space to display your content...with 960, it's 960 pixels. Mine is more custom, but this provides the concept. You can divide this by quite a few numbers, which becomes the basis for how to split the grid. Using this approach, I can easily define a column from grid_1 to grid_4, and it will take a width that is a commensurate percentage of the overall width (i.e. on a 16 column layout doing a 4 column div would cover 25%) It's cross-browser compatible, and doesn't require an overt amount of clear divs. You just need to make the numbers add up to match the amount of columns you want to work with.

Now, I begin by doing the math to figure out how much time each column represents. I assemble each day using a foreach loop: I start with the hour of the display start time and increment up. If the start_time of an event equals the incrementer, I start a div that's styled appropriately based on my coloring criteria. Likewise, if my end time <= the incrementer, I stop the div and define the column's width in the id. Obviously, at the end of the loop, I do an incrementer++. Repeat per day that you display.

My concept is doing this on an time basis for a weekly type calendar. But the overall idea could easily be modified for a month-style calendar or even for a day calendar.

Tables definitely make this easier (version 1 was tables) but it can be done either way if you have the patience.

IE9: Why setting "-ms-transform" works from css, but not with jquery.css()

13 votes

This works

div{
    -ms-transform: rotate(30deg);
}

And following does not

$("div").css("-ms-transform","rotate(30deg)");

Any ideas why, and how to fix it?
Same thing works good on all other browsers, but not on IE. Ofcourse, only IE9 supports it. Older versions dont.

Not sure why As KooiInc says, dashes in style property names are invalid in DOM scripting.

You can fix it by using object notation and passing in the name in camel case instead of hyphenated, like this:

$('div').css({ msTransform: 'rotate(30deg)' });

jsFiddle preview

Combine jQuery and Zen-Coding php ports to emulate client side programming style on server side scripts

9 votes

When I write client side code, I use HTML/CSS/JavaScript and lately jQuery to both speed up coding, and use improved methods to achieve the same goal.

In my text editor I use zen-coding to speed up the writing of code, and also to avoid errors. I was looking at zen-coding as a jQuery plugin for a while, but it has a fatal flaw, that you want the HTML to be written and sent to the client plain before any javascript kicks in.

Although we can use JavaScript servers (env.js or node.js) and therefore do a lot of development server side using JavaScript and jQuery, I am not comfortable moving over yet as it is an emerging technology, and has many differences and drawbacks (and also some major advantages).

I want to continue using PHP server side, but develop in the way I am most comfortable with, and familiar with which is client side JavaScript.

Therefore - I have been looking into QueryPath which is a PHP port of jQuery that aims to take the best and most relevant parts of jQuery and re-work it to suit the server environment.

That is all great, and I have now been looking at two PHP classes capable of parsing zen-coding which when combined acts as a great templating engine and also avoids errors in my code.

The problem I am having is that neither zen-coding parsers support anywhere near a full set of zen-coding features.

So finally my questions (sorry for the rather lengthy intro)

  1. Is there a better server side zen-coding parser I can use in my PHP code?
  2. Is there a good (very concise and full featured) alternative templating system to using zen-coding? (which I know is not originally designed for this task)
  3. Is there a better approach I should take to achieve my ultimate goal of narrowing the divide between the way I code client side and server side?
  4. Is there a PHP library that implements a load of utility functions that by using will enhance the security/performance of my code without me learning all the internal workings? (like jQuery does for javascript)

NB: I am looking more for functional equivalence than syntactic similarity - although both are a plus for me.

Here is some commented test code that should illuminate what I am trying to achieve:

<?php

    // first php based zen-coding parser
    // http://code.google.com/p/zen-php
    require_once 'ZenPHP/ZenPHP.php';
    // my own wrapper function
    function zp($abbr){ return ZenPHP::expand($abbr); }

    // second php based zen-coding parser
    // https://github.com/philipwalton/PW_Zen_Coder
    require_once 'PW_Zen_Coder/PW_Zen_Coder.php';
    $zc = new PW_Zen_Coder;
    // my own wrapper function
    function pwzc($abbr){ global $zc; return $zc->expand($abbr); }

    // php port of jQuery with a new server-side flavor
    // http://querypath.org/
    require_once 'QueryPath/QueryPath.php';

    // initialize query path with simple html document structure
    qp(zp('html>head+body'))

        // add a heading and paragraph to the body
        ->find('body')
        ->html(zp('h1{Zen Coding and jQuery - Server Side}+p{This has all been implemented as a php port of JavaScript libraries}'))

        // add a comments link to the paragraph
        ->find('p')
        ->append(pwzc('span.comments>a[href=mailto:this@comment.com]{send a comment}'))

        // decide to use some jquery - so add it to the head
        ->find(':root head')
        ->append(zp('script[type=text/javascript][src=/jquery.js]'))

        // add an alert script to announce use of jQuery
        ->find(':root body')
        ->append(zp('script[type=text/javascript]{$(function(){ alert("just decided to use some jQuery") })}'))

        // send it to the browser!
        ->writeHTML();

    /* This will output the following html

    <html>
    <head>
    <script type="text/javascript" src="/jquery.js"></script>
    </head>
    <body>
    <h1>
        Zen Coding and jQuery - Server Side
    </h1>
    <p>
        This has all been implemented as a php port of JavaScript libraries
    <span class="comments">
        <a href="mailto:this@comment.com">

            send a comment
        </a>
    </span>
    </p>
    <script type="text/javascript">
        $(function(){ alert("just decided to use some jQuery") })
    </script>
    </body>
    </html>

    */
?>

Any help is much appreciated

Hi Billy,

first of all i want to say i have up-voted your answer because it is well explained and have some nice point to consider; then i want let you think about theese other point:

GOTCHAS

  1. IMHO you are overcomplicating the whole thing ;)

  2. between the entire PHP code needed to generate the HTML and the outputted HTML itself there is very very low difference in term of lenght of writed-code.

  3. the code is completely unredeable for everyone who don't know the 3 libs or whatever it is.

  4. the speed of site-load will decrease enourmously compared to the semplicity of the vanilla HTML.

  5. what the real difference between:


h1{Zen Coding and jQuery - Server Side}+p{This has all been implemented as a php port of JavaScript libraries}

and

<h1>Zen Coding and jQuery - Server Side</h1><p>This has all been implemented as a php port of JavaScript libraries</p>

6.. as you know both zen-coding and queryPath are not intended to be used the way you are doing, at least not in a production scenario.

7.. The fact that jQuery have a good documentation and it's usefull to use doesn't mean that can be used successfully from anyone. ( the mere copy/past is not considered a coding skill IMO )

SOLUTION

it is probably the best solution for you looking at some kind of PHP Templating Engine like smarty, this will suit your needs in various way:

  1. security/performance
  2. narrowing the divide between the way I code client side and server side

an example would be: ( to be considered a very primitive example, smarty have more powerfull functionalities )

<!-- index.tpl -->
<html>
  <head> {$scriptLink} 
  </head>
  <body> <h1> {$h1Text} </h1>
    <p> {$pText} 
      <span class="comments">
        <a href="{$aLink}"> {$aText} </a>
      </span>
    </p> {$scriptFunc} 
  </body>
</html>

    // index.php
    require('Smarty.class.php');
    $smarty = new Smarty;
    $smarty->assign("scriptLink", "<script type=\"text/javascript\" src=\"/jquery.js\"></script>");
    $smarty->assign("scriptFunc", "<script type=\"text/javascript\">$(function(){ alert(\"hello world\") });</script>");
    $smarty->assign("h1Text", "Zen Coding and jQuery - Server Side");
    $smarty->assign("pText", "This has all been implemented as a php port of JavaScript libraries");
    $smarty->assign("aText", "send a comment");
    $smarty->assign("aLink", "mailto:this@comment.com|mailCheck");
    $smarty->display('index.tpl');

NOTE: the use of mailCheck, yes you should also consider eventuality some kind of variable check. smarty can do it....

hope this help. ;)

What are jQuery's most important challenges, and what as a developer can I do about them?

9 votes

I have a project coming up to build an interface which allows a user to construct content with pre-defined templates and code snippets.

We've already decided to use the jQuery and jQuery UI frameworks to help us with the dragging/dropping/sorting parts. There also needs to be some edit-in-place, and I'm going to use contenteditable combined with jQuery's CSS functions.

I already have quite a bit of experience with both frameworks (and love them), but my typical project so far has run to about 50 lines whereas this one will run to a lot more than that, using more of the functions and writing my own plugins.

Before I start work on the project I'm wondering if there are any common pitfalls with jQuery - kind of like 'jQuery - the Bad Parts'. Are there functions that are just best avoided? Are there functions which need working around?

I read this link but it's now 2 years old and a lot has changed in jQuery (and browsers) since then.

Any 'Use this framework instead' or 'Don't use a framework' answers will be ignored - I have to use jQuery. Any 'jQuery is rubbish' rants that don't provide solutions will also be ignored. Constructive comments only please. If I knew how to do better in JavaScript what jQuery does, I wouldn't be using jQuery.

I'll answer half of your question. Here's a laundry list of pitfalls based on painful experience, not all of which I have solutions to.

  • The temptation to make heavy use of long chains of selectors ("ul#leftnav li p a.current ") makes your code brittle. It may FEEL clever ("Hey, I'm teh CSS master!"), but it breaks easily when layout changes in any non-trivial way.
  • Using the DOM as the database. It seems like a neat idea to use .data() to attach data to your DOM elements, to track your page state, and to link DOM elements together, but if you go overboard, you start to lose track of what's where.
  • Putting way too much stuff in $(document).ready(). Once again, it's natural to initialize all your events and data here, but you soon run into organizational and ordering problems. Look into MVC-like solutions to keep things organized.
  • Not quite cross-browser. Test in all targeted browsers early and often! jQuery, although a wonderful abstraction, is still a leaky one. Events and attributes don't always behave exactly the same in different JS engines.

What is the purpose/benefit of using ignored parameters in a JavaScript function?

8 votes

Just so there is no misunderstanding, this question is not about allowing for optional parameters in a JS function.

My question is motiviated by the jQuery parseXML function, which is defined in jQuery.js as follows:

// Cross-browser xml parsing
// (xml & tmp used internally)
parseXML: function( data, xml, tmp ) { 
   ... 
} 

Within the body of the function, the parameters xml and and tmp are both assigned before they are used. That means they are being used as local variables, so the function could have been defined like this:

parseXML: function(data) { 
   var xml, tmp;
   ... 
}

What is the benefit of doing it the first way, other than saving a few characters in the minified version of jQuery.js?

If we define two functions...

function a ( foo ) { }
function b ( foo, bar, baz ) {}

...they'll report different lengths...

console.log( [a.length, b.length] ); // logs [1, 3]

It's very rare to see this little known feature of javascript used.

But apart from shaving a couple of bytes off the minified file-size, this is the only other reason that I can think of.

Web app - slider showing days of the months feature

8 votes

Hi.

For a school project we have to build a web app. I'll be creating something where people can keep track of their classes, their homework, and their free time. A planner/calendar. (I'm making it sound really lame here but hey, I'm tired and English isn't my first language ;) )

I'll be working in CodeIgniter for the PHP logic, combined with the usual.. CSS, jQuery, mySQL. PHP is a requirement for the course; I chose to do this in CI because well.. I wanted to learn the framework. We kind of have to show off what we can do at this point of our 'school career'.

Anyway, I would like to ask for some insights regarding a feature I want to implement. At the top of my page, I would like to show a bar which contains the days of the month. Below the day number, I would be showing how many tasks are added on that day by means of some dots. When the user clicks previous or next, I want to show the previous/next month's days. I also want some sort of slider underneath this box which the user can use to slide left and right, and cycle through the days that way. I hope that made sense?

EDIT 2: I want the slider to be dynamic. If the user slides to the previous or next months, or clicks the buttons, I want it to load the days of the previous/next months and show those. Also, say we're at the 26th of a month, the slider would have to show something like 10-31 of this month AND 1-10 of the next month. I suppose I'll also have to change my month indication (not like in the image here) so a user knows when another month starts (I'll show them the name of the month).

Here's a picture (don't mind the day numbers being messed up, I was lazy doing that correctly in Photoshop. will fix that tomo): Day bar, dont mind the numbers

I've been looking at the jQuery UI sliders. I suppose I'd have to grab the number of days from a database or by using PHP? I guess the cal_days_in_month function could come in handy here. When the user clicks on the arrows or slides left or right, I don't want the page to refresh. Should I go with ajax calls there? I'm not quite sure how to implement this, to be honest. The numbers are also links to a calendar type of view which shows underneath this bar. Could I possibly use the CI Calendar class for this? Or is it more for full-fledged google calendar-type of calendars? I thought this screencast could perhaps be useful?

If possible, could someone please provide some insights on how to start working on this and which plugins/etc I could perhaps use? I'm not sure where to start, to be honest. I'm sure I can work this out somehow, but I guess it'd be nice to get a kickstart by means of some help here. The main problem I'm seeing is the slider/next/previous thing and loading in the previous/next month's days.

Thanks in advance.

EDIT: I realise some people might say/think 'OMG, why don't you just use the skills you have instead of trying something you have to ask us about!'. Well, this is because I actually want to learn something while doing this project. Keep in mind, I'm not asking for lines of code here, I'm just asking for some insight on where to start and what stuff to use; perhaps little snippets that can help me out. Thanks.

UPDATE:

I got a very basic 'day bar' working. Still without a slider, nor do the previous and next buttons work, but hey.. at least it fills it in dynamically. It shows the 5 days previous to the current day, then this month till the end. Whatever is left to fill in gets filled with days of the next month. Quite basic. However, I do have a couple of questions!

Since someone told me yesterday that I was breaking design patterns by doing some stuff the way I was doing it, I'm extremely paranoid about the way I'm working now and I would really like some feedback from 'CodeIgniter pro's'. To fill in the 'day bar', I created a helper with a couple of methods. (One method to dynamically fill that 'month year' thing you see in the picture, another method init() which loads the list of the days, like I explained before). I loaded this helper in the controller and I'm now using the methods in my view:

    <ul>
        <?php
            init($current_day_of_month, $current_month, 
                          $current_year, $days_in_current_month, $show_history);
        ?>
    </ul>

The helper then echoes my day values in my view. Is this good or bad practice? I kept thinking the wrong way when I wanted to start writing the code for this.. I wanted to have a function somewhere in my controller and then call it from the view, but I read that I shouldn't be doing it like that.. that I had to reverse my logic. I find it hard to wrap my head around the fact that I have to do this by sending arrays of data to my view (from my controller), so I opted for creating the helper. Good? Bad? Any tips, resources I should read, screencasts I should watch? Thanks a bunch.

The key thing if you want your system to be dynamic is to make the data transmission short. So using Ajax, as icchanobot says, send the request for a specific month. Use get:

'some_controller?m=' + month + '&y=' + year

or even:

'some_controller?next' // or previous

The controller has to get data for the correct month, but not send back the whole month - only the data needed for your display, in a format as tight as possible. You could query how many events run on which days of that month:

SELECT day, count(event) FROM event_table WHERE DATE BETWEEN 'yyyy-mm-01' AND 'yyyy-mm-31' GROUP BY day ORDER BY day;

query needs adapting to your data structure - use a function to get the day from a complete date, and maybe use indexes so that the query returns the data fast.

Then the controller returns a string as short as you can make it, of the relevant data sorted in day order:

1=3,15=1,29=2

That would mean "1st=3 events, 15th=1 event, 29=2 events". If you don't want the number of events then "1,15,2" is enough. Empty days aren't transmitted.

the data is received by an ajax event handler on your web page and you parse it by using split, then populate the slider by using a loop.

Your biggest drag, in a very dynamic application, is if it slows down when you repeatedly ask for the next month and the next. A few tricks:

  • Update the display while waiting for data; you send your query, and while it is being processed, you can slide the month into view, with the correct number of days, looking disabled so that the user knows immediately that they will get their data, and that it is in progress. Then when the data comes, populate and highlight. It will feel instant though it isn't.
  • Avoid processing information the user doesn't want anymore. If somebody clicks "next" three times, they want the data for july, not may, june and july. Don't process what you don't display.
  • Cache data you've already asked, unless you want the system to return dynamically to the server for the latest state of the calendar. You've asked for the data for May and June, but not displayed it; when the user hits "back", don't ask for that data again.

Good luck!

Are there any good node.js tutorials for absolute beginners?

8 votes

Are there any good and clear node.js tutorials for absolute beginners from A to Z?

I have moderate Javascript and jQuery skills.

Thank you very much.

DailyJS's nodepad tutorials.

It explains the fundamentals of creating a web app with node.js, by creating a notepad app with you, right from framework selection and installation, to databases, connectivity, templates and more.

It even includes full source code on github, so you can actually follow along.

The series is still running at the moment (at part 22, and updated weekly), so there's plenty of material to follow.

Does using $this instead of $(this) provide a performance enhancement?

8 votes

Hello,

Assume I have the following example:

Example One

$('.my_Selector_Selected_More_Than_One_Element').each(function() {
    $(this).stuff();
    $(this).moreStuff();
    $(this).otherStuff();
    $(this).herStuff();
    $(this).myStuff();
    $(this).theirStuff();
    $(this).children().each(function(){
        howMuchStuff();
    });
    $(this).tooMuchStuff();
    // Plus just some regular stuff
    $(this).css('display','none');
    $(this).css('font-weight','bold');
    $(this).has('.hisBabiesStuff').css('color','light blue');
    $(this).has('.herBabiesStuff').css('color','pink');
}

Now, it could be:

Example Two

$('.my_Selector_Selected_More_Than_One_Element').each(function() {
    $this = $(this);
    $this.stuff();
    $this.moreStuff();
    $this.otherStuff();
    $this.herStuff();
    $this.myStuff();
    $this.theirStuff();
    $this.children().each(function(){
        howMuchStuff();
    });
    $this.tooMuchStuff();
    // Plus just some regular stuff
    $this.css('display','none');
    $this.css('font-weight','bold');
    $this.has('.hisBabiesStuff').css('color','light blue');
    $this.has('.herBabiesStuff').css('color','pink');
}

The point isn't the actual code, but the use of $(this) when it is used more than once/twice/three times or more.

Am I better off performance-wise using example two than example one (maybe with an explanation why or why not)?

EDIT/NOTE

I suspect that two is better one; what I was a little fearful of was peppering my code with $this and than inadvertently introducing a potentially difficult-to-diagnosis bug when I inevitably forget to add the $this to an event handler. So should I use var $this = $(this), or $this = $(this) for this?

Thanks!

EDIT

As Scott points out below, this is considered caching in jQuery.

http://jquery-howto.blogspot.com/2008/12/caching-in-jquery.html

Jared

Yes, definitely use $this.

A new jQuery object must be constructed each time you use $(this), while $this keeps the same object for reuse.


A performance test shows that $(this) is significantly slower than $this. However, as both are performing millions of operations a second, it is unlikely either will have any real impact, but it is better practice to reuse jQuery objects anyway. Where real performance impacts arise is when a selector, rather than a DOM object, is repeatedly passed to the jQuery constructor - e.g. $('p').


As for the use of var, again always use var to declare new variables. By doing so, the variable will only be accessible in the function it is declared in, and will not conflict with other functions.


Even better, jQuery is designed to be used with chaining, so take advantage of this where possible. Instead of declaring a variable and calling functions on it multiple times:

var $this = $(this);
$this.addClass('aClass');
$this.text('Hello');

...chain the functions together to make the use of an additional variable unecessary:

$(this).addClass('aClass').text('Hello');

Jquery plugins occupy the same function name -> conflict

8 votes

Hi there.

I've ran into a problem using jquery expose plugin alongside Masked Input plugin. The problem is they both occupy $.mask function which leads to conflict. But I vitally need this two plugins to work together. I would rename $.mask in one of them to... let's say, $.msk, but in this case I'll always need to remember it and if I want to upgrade to new version, I will rename again.

Looking for better solution on how to cope with this kind of conflicts between jquery plugins.

Ok. I'm answering my question now.

I've considered mu is too short's approach, but it's not quite fits. My colleague offered following:

We create new instance of jQuery like so:

var $$$ = $.extend( true, function(selector, context) {
    return new $$$.fn.init( selector, context );
}, $);
$$$.fn = $$$.prototype = jQuery.prototype;

And we create plugins closure of $ function on it (since $ is used inside of plugin):

(function($) {
... plugin code goes here ...
$.fn.extend({
        myplugin: function(maybe_some_options) {
...
})($$$);

Now we can call $$$(<selector>).myplugin( { do : 'great job', and : 'be happy' } ); and $(<selector>).myplugin() at the same time.

We have no problems with this approach so far and I don't see a reason why it would break, so we decided to go with this decision.

Live chat with PHP and jQuery. Where to store information? Mysql or file?

7 votes

There are 1 on 1 live chat. Two solutions:

1) I store every message into database and with jQuery's help I check if there is a new message in database every second. Of course I use cache either. If there is, we give that message.

2) I store every message in one html file and every second through jQuery that file is shown over and over again.

What is better? Or there is third option? And in general, what is better, mysql or file for this kinda project?

Thank you very much.

P.S. The most important question is: what is more efficient and what way will eat less resources!

Edit: And is it, nowadays, very bad for many chats (let's say 2,500 chats, that means 5,000 users) to use long polling and check when file was edited every second through javascript? I use very similiar methods like this chat: http://css-tricks.com/jquery-php-chat/ Will it kill my hosting?

Everyone has given a wide range of opinions but I don't think anyone has really hit the nail on the head.

When it comes down to storing data, the amount of data, the rate it is to be accessed, and several other factors all determine what's the best storage platform.

Some people have suggested using memcached. Now although this is a valid answer (you can use it), I don't think that this is a good idea, solely based on the fact that memcached stores data within your server's memory.

Your memory is not for data storage, it's for use of the actual applications, operating system, shared libraries, etc.

Storing data within the memory can cause a lot of issues with other applications currently running. If you store too much data in your RAM your applications would not be able to complete operations assigned to them.

Although this is faster then a disk based storage platform such as MySQL, it's not as reliable.

I would personally use MySQL as your storage engine server-side. This would reduce the amount of problems you would come across and also makes the data very manageable.

To speed up the responses to your clients I would look at running node on your server.

This is because it's event driven and non-blocking.

What does that mean?

Well, when Client A requests some data that is stored on the hard drive, traditionally PHP might say to the C++, fetch me this chunk of data stored on this sector of the hard drive. C++ would say 'ok no problem', and while it goes of to get the information PHP would sit and wait for the data to be read and returned before it continues it's operations, blocking all other client's in the meantime.

With node, it's slightly different. Node will say to the kernel, 'fetch me this chunk of information and when your done, give me call', and then it continues to take requests from other clients that may not need disk access.

So suddenly because we have assigned a callback to the kernel, we do not have to wait :), happy days.

Take a look at this image: Node Event Loop

This really could be the answer your looking for, please see the following for a more descriptive and detailed information regarding how node could be the right choice for you:

Revert a jQuery draggable object back to its original container on out event of droppable

7 votes

I have a draggable item which if not dropped in a droppable will revert. This works well until a user drops an item in the droppable. If they decide they've made a mistake anytime they pull the draggable out it reverts to the droppable. I would prefer that on out and deactivate the draggable goes back to its original container.

My code is below but I have provided a sample on jsFiddle.

HTML

<div id="origin">
    <div id="draggable" class="ui-widget-content">
        <p>I revert when I'm not dropped</p>
    </div>
</div>
<div id="droppable" class="ui-widget-header">
    <p>Drop me here</p>
</div>

JavaScript

$(function() {
    $("#draggable").draggable({ 
        revert:  function(dropped) {
           var dropped = dropped && dropped[0].id == "droppable";
           if(!dropped) alert("I'm reverting!");
           return !dropped;
        } 
    }).each(function() {
        var top = $(this).position().top;
        var left = $(this).position().left;
        $(this).data('orgTop', top);
        $(this).data('orgLeft', left);
    });

    $("#droppable").droppable({
        activeClass: 'ui-state-hover',
        hoverClass: 'ui-state-active',
        drop: function(event, ui) {
            $(this).addClass('ui-state-highlight').find('p').html('Dropped!');
        },
        out: function(event, ui) {
                // doesn't work but something like this
                ui.draggable.mouseup(function () {
                var top = ui.draggable.data('orgTop');
                var left = ui.draggable.data('orgLeft');
                ui.position = { top: top, left: left };
            });
        }
    });
});

$(function () {
    $("#draggable").draggable({
        revert: function (event, ui) {
            //overwrite original position
            $(this).data("draggable").originalPosition = {
                top: 0,
                left: 0
            };
            //return boolean
            return !event;
        }
    });
    $("#droppable").droppable();
});

Will jQuery ever return a CSS measurement in something other than px?

7 votes

I'm rewritting my Textarea Line Count plugin (<-- shameless plug), and have this question:

When I call $("#someElement").css("letter-spacing"), will I ever get a value in ems, or anything other than px? Based on this example: http://jsfiddle.net/xhhr2/, in Google Chrome at least, it appears that either jQuery or the browser is converting the measurement to px for me. Can I always expect this behavior?

According to Crescent Fresh's answer that links to a hack by Dean Edwards, jQuery goes through great lengths to return the actual, computed pixel value across all browsers and not what was defined originally in the style sheet, so it seems that yes, you can rely on it.

Sending notification to the user on database change

5 votes

I am building a cafeteria management system in which there are two types of users;customres & counter owners.

For each dish offered in cafeteria, there is aunique dish.id associated to it.

Till now, I have dome something like student sends a POST request with dish,id and counter number to a URL which updates the "orders table'(which has PK as id). When the dish is prepared, the counter owner presses "Prepeared" button.

At this point, I want the customer whose order is next to what is prepared to get notified that "Your order preparation is in progress."

How should I do it? One way is to simply make a view which has its argument as customer.id & status and it replies with True or Flase. I can simply poll the URL and provide the notification if I recieve True.

But, I feel like polling is not a better approach as there will be so many customers logged in and each will poll to the server which is not acceptible. Any better way?

It really depends what you really need.

If notification can be sent ad part of user activity, simply add a user message, and it will be displayed whenever user do an action on the page. django.contrib.messages plus few lines in your main html template will do it.

But if you want the notification to be interactive - you can use one of the few PUSH options

Interesting links:

From the servers side, there are few options available, the simplest is Green Unicorn. Using it will allow you to have few thousands connections open and managed by only few processes.

jQuery, ajax, php, msyql: auto-suggest form input

5 votes

I have a mysql db table that has every U.S. city, state, zip, lat, long. On my site page I have a form input for cities. As the user types, I'd like to suggest city, state. What current practices/techniques are good? (Limitations are jQuery, PHP, MYSQL)

Solution

jQuery UI has a nice autocomplete feature.

JQuery UI Autocomplete

It is quite well configurable. You should send the data in JSON format from the server, Autocomplete will mostly handle the rest. Check out the docs.

How to run a script after client validation in asp.net mvc

5 votes

I am disabling my submit buttons when submitting a form, for preventing the user to submit the form multiple times.

$(function ()
{
    $("form").submit(function ()
    {
        $(":submit", this).attr("disabled", "disabled");
    });
});

But if the client validation fails I want to enable the button again. I am using asp.net mvc unobtrusive client validation

You can use the jQuery One event as detailed in this answer.

Most solutions to this issue revolve around testing $("form").valid() - you could probably use this in your function to determine whether to disable the submit button.

How do I use Google Maps geocoder.getLatLng() and store its result in a database?

5 votes

Hey everybody! Im trying to use getLatLng() to geocode a list of postal/zip codes and store the generated point in the database to be placed on a map later. This is what I've got so far:

 $(".geocodethis").click(function () {
    var geocoder = new GClientGeocoder();
    var postalCode = $(this).siblings(".postal").val();
    var id = $(this).siblings(".id").val();

    geocoder.getLatLng(postalCode, function (point) {
        if (!point) {
            alert(postalCode + " not found");
        } else {
            alert(point);
            var serializedPoint = $.param(point);                
            //Geocode(id, point);
        }
    });

});

function Geocode(id, point) {
    alert(point);
    $.post("/Demographic/Geocode/" + id, point, function () {
        alert("success?");
    });
}

but I'm getting this.lat is not a function in my error console when i try to serialize the point object or use it in $.post()

From my research, I understand that geocoder.getLatLng() is asynchronous, how would that affect what I'm trying to do? I'm not running this code in a loop, and I'm trying to post the point using the anonymous callback function.

How can I save the information from point to use later?

Update

Creating a marker and trying to post that still results in the this.lat is not a function in the error console.

$(".geocodethis").click(function () {
        var geocoder = new GClientGeocoder();
        var postalCode = $(this).siblings(".postal").val();
        var id = $(this).siblings(".id").val();

        geocoder.getLatLng(postalCode, function (point) {
            if (!point) {
                alert(postalCode + " not found");
            } else {
                alert(point);
                var marker = new GMarker(point);

                $.post("/Demographic/Geocode/" + id, marker, function () {
                    alert("success?");
                });
            }
        });

    });

** Another Update **

I really need to save the geocoded address for later, even if I store the latitude/longitude values in my database and remake the marker when I'm ready to put it onto a map. Again, serializing or posting - seemingly using the point in any way other than in google maps functions gives the this.lat is not a function exception in my error log.

I'm using asp.net mvc - are there any frameworks out there that would make this easier? I really need help with this. Thanks.

If your stuck for 2 days maybe a fresh v3 start would be a good thing, this snipped does a similair job for me...

          function GetLocation(address) {
          var geocoder = new google.maps.Geocoder();
          geocoder.geocode({ 'address': address }, function (results, status) {
              if (status == google.maps.GeocoderStatus.OK) {
                  ParseLocation(results[0].geometry.location);

              }
              else
                alert('error: ' status);

          });
      }

  }

  function ParseLocation(location) {

      var lat = location.lat().toString().substr(0, 12);
      var lng = location.lng().toString().substr(0, 12);

      //use $.get to save the lat lng in the database
      $.get('MatchLatLang.ashx?action=setlatlong&lat=' + lat + '&lng=' + lng,
            function (data) {
                // fill textboss (feedback purposes only) 
                //with the found and saved lat lng values
                $('#tbxlat').val(lat);
                $('#tbxlng').val(lng);
                $('#spnstatus').text(data);


            });
    }

Twitter and jQuery , render tweeted links

4 votes

I am using jquery ajax to pull from the twitter api, i'm sure there's a easy way, but I can't find it on how to get the "tweet" to render any links that were tweeted to appear as a link. Right now it's only text.

$.ajax({  
            type : 'GET',  
            dataType : 'jsonp',  
            url : 'http://search.twitter.com/search.json?q=nettuts&rpp=2',  

            success : function(tweets) {  
               var twitter = $.map(tweets.results, function(obj, index) {  
                  return {  
                     username : obj.from_user,  
                     tweet : obj.text,  
                     imgSource : obj.profile_image_url,  
                     geo : obj.geo  
                  };  
               });  

UPDATE: The following function (plugin) works perfectly.

(function($) {

    $.socialFader = function(options) {

        var settings = {
            tweetHolder : null,
            tweetCount  : 100,
            fadeSpeed   : 500,
            tweetName: 'jquery'
        };  

        if (options) {
            $.extend(settings, options);
        };

        var URL = "http://search.twitter.com/search.json?q="+settings.tweetName+"&rpp=" + settings.tweetCount + "&callback=?";

        function relative_time(time_value) {

            var values = time_value.split(" ");
            time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
            var parsed_date = Date.parse(time_value);
            var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
            var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
            delta = delta + (relative_to.getTimezoneOffset() * 60);
            var r = '';
            if (delta < 60) {
                r = 'a minute ago';
            } else if(delta < 120) {
                r = 'couple of minutes ago';
            } else if(delta < (45*60)) {
                r = (parseInt(delta / 60)).toString() + ' minutes ago';
            } else if(delta < (90*60)) {
                r = 'an hour ago';
            } else if(delta < (24*60*60)) {
                r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
            } else if(delta < (48*60*60)) {
                r = '1 day ago';
            } else {
                r = (parseInt(delta / 86400)).toString() + ' days ago';
            }

         return r;

        };

        String.prototype.hashify = function() {
            return this.replace(/#([A-Za-z0-9\/\.]*)/g, function(m) {
                return '<a target="_new" href="http://twitter.com/search?q=' + m.replace('#','') + '">' + m + "</a>";
            });
        };

        String.prototype.linkify = function(){
            return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
                return m.link(m);
            });
        };

        String.prototype.atify = function() {
            return this.replace(/@[\w]+/g, function(m) {
                return '<a href="http://www.twitter.com/' + m.replace('@','') + '">' + m + "</a>";
            });
        }; 

        $.getJSON(URL, function(JSON) {

            $.each(JSON.results, function(i, tweet) {

                var profilePicture = tweet.profile_image_url;
                var userLink = tweet.from_user;
                var text = tweet.text;
                text = text.linkify().atify().hashify();
                var createdAt = new Date(tweet.created_at);
                var myTweet = '<a href="http://www.twitter.com/' + userLink + '" title="' + userLink + '">' + userLink + '</a> ';
                myTweet += text;
                $(settings.tweetHolder).append('<li class="cycles">' + myTweet + '</li>');

            });

            var elements = $(settings.tweetHolder).children();
            var timeOutStart = 5000;

            function fader(elementId) {
                setTimeout(function() {
                    $(elements[elementId]).fadeOut(settings.fadeSpeed, function() {
                        $(elements[elementId + 1]).fadeIn(settings.fadeSpeed);
                    });
                }, timeOutStart * (elementId));
            };

            for (var j = 0; j < elements.length; j++) {
                           fader(j);
                       };

        });

    };

})(jQuery);

Within my Ready Statement :

$.socialFader({ tweetHolder:"#twitter", tweetName:"nettuts", tweetCount:2 });

Here is a plugin I wrote which really simplifies the tweet/json aggregation then parsing. It fades the tweets in and out. Just grab the needed code. Enjoy.

(function($) {

    $.socialFader = function(options) {

        var settings = {
            tweetHolder : null,
            tweetCount  : 99,
            fadeSpeed   : 500,
        };  

        if (options) {
            $.extend(settings, options);
        };

        var URL = "http://search.twitter.com/search.json?q=jquery&rpp=" + settings.tweetCount + "&callback=?";

        function relative_time(time_value) {

            var values = time_value.split(" ");
            time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
            var parsed_date = Date.parse(time_value);
            var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
            var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
            delta = delta + (relative_to.getTimezoneOffset() * 60);
            var r = '';
            if (delta < 60) {
                r = 'a minute ago';
            } else if(delta < 120) {
                r = 'couple of minutes ago';
            } else if(delta < (45*60)) {
                r = (parseInt(delta / 60)).toString() + ' minutes ago';
            } else if(delta < (90*60)) {
                r = 'an hour ago';
            } else if(delta < (24*60*60)) {
                r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
            } else if(delta < (48*60*60)) {
                r = '1 day ago';
            } else {
                r = (parseInt(delta / 86400)).toString() + ' days ago';
            }

         return r;

        };

        String.prototype.hashify = function() {
            return this.replace(/#([A-Za-z0-9\/\.]*)/g, function(m) {
                return '<a target="_new" href="http://twitter.com/search?q=' + m.replace('#','') + '">' + m + "</a>";
            });
        };

        String.prototype.linkify = function(){
            return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
                return m.link(m);
            });
        };

        String.prototype.atify = function() {
            return this.replace(/@[\w]+/g, function(m) {
                return '<a href="http://www.twitter.com/' + m.replace('@','') + '">' + m + "</a>";
            });
        }; 

        $.getJSON(URL, function(JSON) {

            $.each(JSON.results, function(i, tweet) {

                var profilePicture = tweet.profile_image_url;
                var userLink = tweet.from_user;
                var text = tweet.text;
                text = text.linkify().atify().hashify();
                var createdAt = new Date(tweet.created_at);
                var myTweet = '<a href="http://www.twitter.com/' + userLink + '" title="' + userLink + '">' + userLink + '</a> ';
                myTweet += text;
                $(settings.tweetHolder).append('<li class="cycles">' + myTweet + '</li>');

            });

            var elements = $(settings.tweetHolder).children();
            var timeOutStart = 5000;

            function fader(elementId) {
                setTimeout(function() {
                    $(elements[elementId]).fadeOut(settings.fadeSpeed, function() {
                        $(elements[elementId + 1]).fadeIn(settings.fadeSpeed);
                    });
                }, timeOutStart * (elementId));
            };

            for (var j = 0; j < elements.length; j++) {
                fader(j);
            };

        });

    };

})(jQuery);

backbone.js - getting extra data along with the request

4 votes

I have a collection which holds some of the users. Some information that is needed is how many total there are, how many pages, etc. How do I pass these back to the client? Or do they have to come from a separate view in which case I will need more than one ajax call? I'd like to have the collection fetch() and also receive some of this "meta data". What's a good way for handling this?

Generally, you need to handle this in the collection class' parse method. Its responsibility is to take the response and return back an array of model attributes. However, you could do more than that if you wished if you didn't mind the parse method having this additional responsibility.

UserList = Backbone.Collection.extend({

    model: User,

    url: '/users',

    parse: function(data) {
        if (!data) {
            this.registered_users = 0;
            return []; 
        } 
        this.registered_users = data.registered_users;
        var users = _(data.users).map(
            function(user_data) {
                var user = {};
                user['name'] = user_data.name;          
                return user;
            }
        );
        return users;
    }

});

So in the trivial example above, presume the server returns a response which contains a count of registered users and and an array of user attributes. You would both parse through and return the user attributes and you would pick off the registered user count and just set it as a variable on the model. The parse method would get called as part of a fetch. So no need to modify the fetch, just use the built-in hook method that you have.

Purists would say that you are giving the parse method a secondary responsibility which might surprise some people (e.g. returning something and modifying model state). However, I think this is okay.