--- layout: archive title: Zulip Chat Archive permalink: /stream/116395-maths/topic/topological.20space.20docs.html ---
Ok so after a ropey start (see my heq thread earlier) I made it through the topological_space.lean
file today and wrote some docs on it: https://github.com/kbuzzard/mathlib/blob/docs-topspaces/docs/theories/topological_spaces.md . I needed to read this file for my work on schemes -- in particular I had to finally understand what a filter was and what they had to do with topological spaces.
You are a bit unfair with filters. You should at least explain that they allow to cover uniformly the cases of sequences and maps from topological spaces. And then slightly more exotic stuff like one-sided limits at some real. That's why Bourbaki invented them.
They also allow to mimic using sequential continuity and compactness for non-metric spaces
One way to motivate them is to consider the ~16 variations on L'hopital's theorem that arise with lots of permutations of limits to different places in the domain and codomain
I was just grumpy about them because they have actively stopped me doing what should be trivial stuff for a couple of days, because I didn't know what \Glb meant
when I actually ploughed through the file and a lot of the imports, and set pp.all on occasionally etc etc and finally got to the bottom of things and discovered that F <= G iff G subseteq F
then it all began to make sense
This is what this definition if compactness is about: a space is compact if every sequence has a converging subsequence,made true for all spaces
The description of topological basis is also a bit grumpy; the point as I mentioned before is to say "a topological basis is a collection of sets satisfying these two axioms" and then fold in the connection to generating a topology
I'm sure it's a very cute way to think about things
yeah, I had to get up early this morning, I've been in a grumpy mood all day :-)
I'm defending filters here but zulip and gitter can testify I went through the same frustrations
In fact I think the "filters are a complete lattice" angle should probably be emphasized more, since it underlies many of the filter-theoretic definitions
A filter which is not bottom is called a proper filter fyi
Mario, the reason I don't buy your explanation is that there is a standard definition of a basis of a topological space, which we all learn, and which is on Wikipedia, and which is not what is implemented, so all your protestations that it's a better way of doing it are cancelled out by the fact that every mathematician will be confused by the way it's done. I have flagged the relevant lemma which saves us.
but it is that definition...
I think Mario had the right idea when I faced that:we keep filters but add lemmas translating to usual stuff in usual situations
[explanation of why bases are done like that]
Yes, I explictly flag the lemmas saying "oh look, compactness looks insane, here's the lemma you need"
"bases look insane, here's the lemma you need"
That's the philosophy of the docs
https://en.wikipedia.org/wiki/Base_(topology)
A base is a collection B of subsets of X satisfying these two properties:
1. The base elements cover X.
2. Let B1, B2 be base elements and let I be their intersection. Then for each x in I, there is a base element B3 containing x and contained in I.
Now I can use topological spaces in Lean, and this morning I couldn't.
Right.
Whereas you have generate_open
it's the generate_open that makes it unusable
I'm sure you could also explain why filters are useful
Any topological basis is a basis for the topology it generates
the lemma you proved and I flagged makes the definition usable
you can always satisfy that clause with refl
My point is simply that if you want to prove that (a,b) x (c,d) is a basis of open sets for the standard topology on R^2, you cannot possibly do that from the definition
but it's easy from the lemma
Yes you can
_you_ can
a mathematician can't
becuase they have no clue how to use generate_open
Those are two different goals though
you are trying to prove that some basis is a basis for something else, rather than just proving it's a basis
My wife says I must stop participating but please be nice :smiley:
In maths, the proof goes "insert argument to prove that if x is in an open set U in R^2 then ther's some (a,b) x (c,d) in U containing x and now we're done
in Lean the proof from the definition of basis goes "that, and then we have to prove something about generate_open"
except now we don't because of the lemma
You have a preconceived topology in that example
yes, the one the mathematicans use :-)
I'm talking about proving that some collection of sets is a basis full stop
I know
but that's a silly notion
That's the one wikipedia discusses
there's no generate_open there
it's the generate_open which makes the definition a complete pain to work with
and it's the lemma that saves us
so I highlight the lemma
that's all
the lemmas are all there
The generate_open is dischargable by refl, like I said
I'm saying the definitions are silly, but that's OK because the lemmas are there
yeah but I don't really know what that means
and I know what the lemma means
If S satisfies axioms 1 and 2, then it is a basis for (generate_open S)
and a generic mathematician will come along
with a proof of the two things in wikipedia
and will want to prove that they have a basis
and so they can use the lemma
okay I get it you think the notion is useless
right
but I'm not saying it shouldn't be there
I'm just explaining why I had to write the docs
but the docs are
and why they came out grumpy :-)
that is an absurd definition of compact as well.
It should be a theorem not a definition.
But again it doesn't matter
anyway, I am not grumpy any more :-)
I'm not sure how much I want to defend this... I think Johannes thought the filter stuff would make everything neat and concise
it doesn't matter
I'm just taking a contrary position for a laugh really
I'm really happy now
I can work topological spaces
I personally have a preference for standard point-set definitions
and I'm hoping that other people with the same background as me (i.e. basically two courses in topology and that's it) can do the same
but there are enough lemmas around to get rid of any filter claims you come across
yeah, that's why Hausdorff is called t2 probably ;-)
t2 is shorter :)
I'm really happy with the lemmas. I was preparing a list of lemmas which you should have proved
and it came out empty in the end
Occasionally it would have size 1 or 2
and then I'd find them :-)
Props to @Johannes Hölzl too.
yeah he gets the credit for most of this work
It's a really nice complete library
even though some definitions are theorems and some theorems are definitions ;-)
I guess you guys can barely tell the difference
you probably think I'm talking about unfolding or something
it will teach you to forget about definitions and worry more about interfaces
OK, enough CS baiting. Thank you for your library!
I need to learn what this word interface means
does API mean something to you?
not really
this is some way of talking to the theorems
or something
Are my docs some sort of attempt to make an API for mathematicians trying to use topological spaces in Lean?
it's the idea that you encapsulate the underlying definition, somehow make it inaccessible, and then only use theorems that express properties of it
encapsulate is another mystery
these are all very CS words
I understand that a mathematician will come along with a proof that every cover has a finite subcover and will want to deduce that their space is compact
so I point them to the lemma which says this
[and make some snarky remark probably about how the definition is something else]
Category theory does this a lot, for example: A product of two objects is some object with a universal property, so that you can only use the universal property to prove stuff rather than unfolding whatever the product is "actually" defined to be in a particular category
universal properties I understand
but I don't understand why this is an argument for giving an unrecognisable definition of compact
A biconditional is also a "universal property", in a sense
biconditional is a theorem of the form X iff Y?
it tells you everything you ever need to know about the definition, without actually telling you what the definition is
I see
but you really need to know where the theorem is
yes, that's the public part
the definition is the private part
Maybe I saw this in java once
your variables are private
and you make some functions which lets the user change them
or read them
without actually letting them fiddle with them directly
sorry, methods
but I didn't realise this had anything to do with topological spaces at the time
One reasonably basic example of a gnarly construction is the Kuratowski pair (a,b) = {{a}, {a, b}}
eew
eew
I see
that's a great example
we just need (a,b) = (c,d) iff a=c and b=d
exactly
so we point the user to where that is proved
and they can't see the disgusting truth behind it all
and later, we might want to change the definition for some reason to, say, {{0,a}, {1, b}} and that's okay as long as we can still prove the defining property, since no user depended on the specific construction
but the compactness thing is different. We go for Kuratowski because all the choices are horrible and this one is the least horrible
I see
it's not completely different
you are reserving the right to invent some even more weird thing that is better than filters
and then change the definition of compactness
because it compiles better on a quantum computer or whatever
or even just the point-set definition
I see. In fact you could just play that trump card and that would shut me up
you should just say "Kevin, you don't understand, the definition we have here works better if your machine has 8 cores"
and I would have no response
the real point is that it shouldn't matter what the actual definition is, and if it does you're doing it wrong
This is different to mathematics
If you wrote a maths book with some weird definitions of things
and then proved theorems which said that they were the same as everyone else's definition
there's also the pedagogical angle, but that's a different issue
people would be confused as to why you were doing it
I don't think that exact thing is unheard of though
and you can't answer "this definition works better if you have 8 brains"
your new definition might be suitable to a particular sort of generalization, for example
As you are probably aware, I am extremely interested in the pedagogical angle
and have very little understanding of stuff like run time analysis and other CS-related matters
in the pedagogical view, you might redefine the same thing several times depending on the current teaching goals
the new definition may not even be the same as earlier ones, although it is usually a generalization or provably equivalent
So ultimately I should not care about your definitions, my main aim is to make sure that the interfaces are there.
exactly
OK maybe tomorrow I will degrump it a bit :-)
but now I have to make a birthday present
lol it's my birthday so I'll just pretend that's for me ;)
ha ha it's for my son's GF
happy birthday
I'm not entirely sure you'd want a plastic T anyway
good mathlib docs are a good present :)
OK well seeing as it's your birthday I de-grumped the docs a bit.
even though it's strictly speaking not even your birthday any more where I'm sitting
I'm now about to get onto the job I meant to do today, which was to prove that Spec(R) is compact using some argument involving bases :-)
now I understand the interface better :-)
Thanks as ever, by the way.
I forget if the contrapositive form of the compactness definition is there: a collection of closed sets with the finite intersection property has nonempty intersection
I didn't see it
and I almost mentioned it as a theorem which should be there
but then I decided I'd never used it in my life :-)
I almost mentioned it the other day when Simon was asking whether the same was true for an arbitrary set
I guess it is somewhat similar to the filter definition
Hmm, I've just realised that I want that a mathlib-basis is a Wikipedia-basis
that's just the first two parts of the definition
oh sorry I don't mean that
If h1
and h2
are proofs of the two axioms, then <h1, h2, rfl>
is a proof it's a mathlib-basis
that's what I've been saying
is_topological_basis_of_open_of_nhds
I mean the converse of that
Yes, sorry, I understand now
I was talking nonsense at some points earlier
when I said "wikipedia definition"
I sometimes meant "hypotheses in is_topological_basis_of_open_of_nhds
"
:-/
mem_nhds_of_is_topological_basis
is the easiest way to get converses of that stuff
https://topospaces.subwiki.org/wiki/Basis_for_a_topological_space
but there should be a theorem saying that a basis element is open
there's a website (which I've never heard of) giving that as the definition.
This is evidence that I am very fluid with what my definition is :-/
mem_nhds means I might have to get my hands dirty with neighbourhoods maybe :-/
which statement are you going for specifically?
if B is a basis then I want that for all U open and for all x in U, there's V in B with x in V in U
because as we all know
50% of the time I will swear blind that this is the definition of a basis in Wikipedia
and I don't want to do induction on generate_open
I want this to be there on a plate
Kenny proved it
in a file called temp.lean :-)
but I was trying to avoid importing this file
because its name looked a bit ominous
I can do this myself
The lemmas I need are all there
I just need to glue them
This morning I didn't know what nhds a was
I have to remember that I'm not scared of it any more
I can add these to the file:
lemma is_open_of_is_topological_basis {s : set α} {b : set (set α)} (hb : is_topological_basis b) (hs : s ∈ b) : _root_.is_open s := is_open_iff_mem_nhds.2 $ λ a as, (mem_nhds_of_is_topological_basis hb).2 ⟨s, hs, as, subset.refl _⟩ lemma mem_subset_basis_of_mem_open {b : set (set α)} (hb : is_topological_basis b) {a:α} (u : set α) (au : a ∈ u) (ou : _root_.is_open u) : ∃v ∈ b, a ∈ v ∧ v ⊆ u := (mem_nhds_of_is_topological_basis hb).1 $ mem_nhds_sets ou au
It's the easy way of is_open_iff_mem_nhds
I need and then I'm done :-)
yeah, what you said
I'd vote for them definitely.
Then I can eschew temp.lean completely
I like mem_nhds_of_is_topological_basis
because it generalizes well to all sorts of bounded quantification over open sets that comes up in topology, like continuity or compactness that can be stated with basis sets
I didn't like it until today because of the obscure definition of nhds
but again there was a lemma -- in this case mem_nhds_sets_iff
-- which made this clear
or even nhds_sets
, which I mention in the docs
I see. I'm mentioning all the results that a mathematician needs for the interface.
eew, exists v \in B
-- I have to run classical.some twice to get that v is in B
You can use exists.fst
for the v \in B
hypothesis
That means exists v in B, P
(B a set) unravels to exists v in X, exists H : v in B, ...
Why not unravel to exists v in X, v in B and ...
You can also use exists v : B, P
to pack them both into one
yeah but you wrote v in B not me ;-)
because that same translation works for a wide variety of binders
I don't know what a binder is
A thing that introduces a bound variable
like exists or forall or lambda
somehow I thought that there were only about three of these
or Glb or Lub
but you're saying "exists v \in B" is somehow another one
or indexed intersection
I see.
No, I'm saying that every binder has the translation Q a R b, p a => Q a, Q (_ : a R b), p a
where Q
is any binder
and R
is any infix operator
unknown identifier 'exists.fst'
should be in logic.basic
It's Exists.fst
so you can use projections
capital E, got it
you use Q again
OK well seeing as it's your birthday I de-grumped the docs a bit.
I think it still misses the main point of using filters: you have limits at a point and limits when a real variable or a natural number goes to infinity gathered in a single definition. For instance uniqueness of limit that you mention in your doc is proved for all three (and more) situations at once. This has nothing to do with "non-mathematical points such as running times".
I just don't know anything about how filters are used in practice so am in no position to be able to write those parts of the docs properly. I've never had to use them before and I don't really care about explaining them for this reason; I just wanted to get down the things I needed to know myself.
@Kevin Buzzard just added your documentation, I guess we can add more comments on filters later.
I think one problem why there is not a lot of knowledge about filters (or nets) in math, is that it is obvious and usually something you don't need to think about. But we are in a formal system, so we are either forced to generalize over limits (using filters or nets) or we produce a lot of duplication (as Mario and Patrick mentioned). We can avoid them and define things like compact
using open covers etc. But some proofs get much more concise using the fact that you can use the complete lattice (and even category theory) properties properties of filters. Currently it is not always intuitive to work with filters, but maybe with more automation and better syntax notations and support from the parser it may get better.
In the end they are a powerful abstraction, and as most abstractions it takes some time to learn it.
Yeah, Mario convinced me not to worry about what was a definition and what was a theorem, as long as the theorems were all there.
There is a very expressive way to use filters, with the word eventually.
def eventually {α : Type} (P : α → Prop) (f : filter α) := {x | P x} ∈ f.sets
Then if you want to say that, eventually, some function u defined on nat is nonnegative, you write
eventually (λn, 0 ≤ u n) at_top
If you want to say the same thing around a point x, say (which corresponds to a filter at x
), you just write it as
eventually (λy, 0 ≤ f y) (at x)
In this way, you can also write readable definitions of limits, or essentially whatever involves filters. This is the only way I use filters in Isabelle, and I was essentially never stuck.
@Johannes Hölzl what do you think about adding (and using) this definition?
I'm fine with adding this definition, especially with a corresponding quantifier notation (and also its dual the frequently
quantifier). I'm just not sure if we should abandon the f.sets
notation or keep both.
I want to refactor the filter stuff so that .sets
is superfluous, i.e. s \in f
means s \in f.sets
. I guess we can support eventually
if it's a reducible
definition, but I don't like the idea of duplicating everything for this purpose
Setting up a has_mem
for filter is surely a good idea.
Last updated: Apr 24 2020 at 19:02 UTC


Let yi= y(xi,t) represent the time-dependent displacement of a particle of mass M with horizontal position xi. Each particle is coupled to its nearest neighbors with a spring in order to form a chain of oscillators. It is assumed that the particles move only in the y-direction and that the force Fi on the i-th particle depends on the relative displacement between that particle and its nearest neighbors. The force on the i-th particle can be written as
where K is the Hook's law coupling constant. Because the first and last particles in the lattice are fixed, we compute particle accelerations starting with the second particle and continuing through the lattice until we reach the next-to-last particle. This, the particles in a chain with N oscillators are labeled [0, 1, 2, .... N-1, N, N+1].
One way of understanding a chain of N coupled oscillators of length L and mass M is to study the motion of its normal modes. A normal mode is a special configuration (state) where every particle moves sinusoidally with the same angular frequency ωm. The m-th mode Φm of the oscillator chain of length L is
.
The system stays in a single mode and every particle oscillates with constant angular frequency ωm if the oscillator chain is initialized in a single mode.
An arbitrary initial configuration can be expressed as sum of these normal modes.


Escalator C07N10
| Station Name | PENTAGON |
| Station Code | C07 |
| Station Description | |
| Escalator Description | Escalator between upper and lower platforms |
Summary
| Num. Breaks | 4 |
| Num. Fixes | 4 |
| Num. Inspections | 4 |
| Availability | 99.578% |
| Report Time Range | 121d 11h 52m |
History
| Time |
Status |
Duration |
| Thu, 09/26/13 03:16 AM |
OPERATIONAL |
4d 21h 14m |
| Thu, 09/26/13 02:29 AM |
SAFETY WORK ORDER |
00h 47m |
| Wed, 09/25/13 05:46 AM |
OPERATIONAL |
20h 42m |
| Tue, 09/24/13 10:48 PM |
MINOR REPAIR |
06h 58m |
| Tue, 09/24/13 06:10 AM |
OPERATIONAL |
16h 38m |
| Mon, 09/23/13 10:55 PM |
MINOR REPAIR |
07h 14m |
| Wed, 09/11/13 05:37 AM |
OPERATIONAL |
12d 17h 17m |
| Tue, 09/10/13 11:26 PM |
PREV. MAINT. INSPECTION |
06h 11m |
| Wed, 08/14/13 05:42 AM |
OPERATIONAL |
27d 17h 43m |
| Tue, 08/13/13 11:33 PM |
PREV. MAINT. INSPECTION |
06h 09m |
| Wed, 07/17/13 11:31 AM |
OPERATIONAL |
27d 12h 01m |
| Wed, 07/17/13 09:52 AM |
CALLBACK/REPAIR |
01h 39m |
| Fri, 07/12/13 03:52 AM |
OPERATIONAL |
5d 05h 59m |
| Thu, 07/11/13 11:09 PM |
PREV. MAINT. INSPECTION |
04h 42m |
| Sun, 06/30/13 02:14 AM |
OPERATIONAL |
11d 20h 55m |
| Sun, 06/30/13 01:25 AM |
CALLBACK/REPAIR |
00h 49m |
| Fri, 06/07/13 04:43 AM |
OPERATIONAL |
22d 20h 41m |
| Thu, 06/06/13 11:58 PM |
PREV. MAINT. INSPECTION |
04h 44m |
| Sat, 06/01/13 12:38 PM |
OPERATIONAL |
5d 11h 20m |
Page Last Updated: 10/01/13 12:31 AM


The TrackTrains.info will help you find a train seat, when there are not more seats.
In order to accept the invitation please follow.


Let me start by giving a simple introduction about my work. I am a Senior Machine Learning Researcher presently employed by product based company. I have worked in several ML projects mainly dealing with Optimization Problems, Explainable AI, Deep Learning, Imbalance Classification, et cetera...
I am also the author of a book "Machine Learning Cookbook with Python" published by BPB publications.
I have been part multiple publications through Journals and Open Publications, along with this I have few applied patents to my name.
Recently I was invited by Arizona State University to be a part of their team participating in CPS challenge 2020 funded by National Science Foundation(NSF), USA and sponsered by NASA.
I have also conducted multiple workshops, seminars in this field of research for various universities and made contributions to Open Source Software as well.


Some reported cases of exam malpractice over the years
by AdminPolice in Koboko arrested a senior five student of Nyarilio Secondary School for impersonating a senior four student
November 05, 2019: The Police in Mpigi arrested Musumba Musisi over theft of Primary Leaving Examinations (PLE) that got underway on Monday 4 Nov. He was arrested after a tip by the administration of Mpigi UMEA Primary School, a government primary school located in Mpigi town council after mathematics papers delivered to the school were found to be unsealed.
February 09, 2019: The Bishop of Ankole Diocese, Rt. Rev. Dr. Sheldon Mwesigwa vowed to fire all teachers involved in exam malpractice in schools under the Church of Uganda in the diocese. Bishop Sheldon was blessing some of Mbarara Junior School's best 2018 PLE performers.
October 26, 2016: Police in Koboko arrested a senior five student of Nyarilio Secondary School for impersonating a senior four student to sit for Uganda Certificate of Education (UCE) exams. Ibrahim Aluma was sitting for a South Sudanese student identified as Abraham Duboul of Midland Secondary school.
October 30, 2016: Two days to PLE Police warned schools and any members of the public against engaging in examination malpractice. While addressing the press at police headquarters in Naguru, then spokesperson Felix Kaweesi, said Police was determined to work with Uganda National Examinations Board (UNEB) to make sure the exercise goes on smoothly.
November 01, 2015: Police arrested a teacher for being involved in exams malpractice in Kampala. According to the UNEB Deputy Secretary Primary Chrysostom Kibedi, the teacher of Kasanga Junior Primary School, Anthony Tibita was apprehended while teaching candidates after briefing.
October 22, 2013: At Duhaga hall in Hoima, Ayena Harriet was found attempting to sit a Chemistry Paper on behalf of Sanyu Happy. The suspect together with her husband identified as Byamukama and were arrested, interrogated and detained at Hoima Police station.
February 07, 2012: Head teachers of 45 secondary schools faced demotion and dismissal over examination malpractices. The then Uganda National Examinations Board (UNEB) Executive Secretary, Matthew Bukenya, said that the affected parties would be accorded a hearing before a final decision would be made on the queried results.


--- layout: page title: "jQuery: Novice to Ninja" prev: OEBPS/ch06.html next: OEBPS/ch08.html book_path: books/earle-castledine-craig-sharkie-jquery-novice-to-ninja-_oeb/ --- {% include JB/setup %} {% raw %}
getElementsByClassName
for
browsers that supported that method. Now it is taking the bold step of
supporting
querySelectorAll
for supporting
browsers. What does this mean for us? Being a method native to the
browser, querySelectorAll
(qSA
) is streets ahead in responsiveness for
compliant browsers, while those browsers lacking support for HTML5
continue to use the methods they currently employ. And the best thing
about qSA
is that all we need to do is provide
jQuery with a selector that will invoke it:$('input[type=text]').css('background-color', 'lemonchiffon')jQuery offers us the potential to create extensions and custom selectors for CSS, but these are always going to be slower than native methods, the only costs of which are slightly longer selectors. Instead of using
:input
or :text
in a filter, we use our
aforementioned selector. Filters still have their place, but you really
should be looking at why you’re using them, given the slowdown
in selection speed as we see in Figure 7.1.
The
:password
filter method, for example,
selects all elements that are password inputs from all the inputs in the
page, and is reasonably quick at 13,589 operations per second. If you
preferred it over input[type='password']
, though,
you’d be losing out on nearly another 13,000 operations. You might not
have over 26,000 elements on the page to select between, but it still
means the selection will get through your elements that much
faster.
It works just as well with [type='radio']
,
[type='image']
, or
[type='submit']
, and as you can see by adding the
preceding element type, you help the browser help you even more.
Rumor has it that filters are slated to be deprecated, so use them
at your own risk. The
:enabled
and
:disabled
filters will fetch elements
based on their disabled
attribute,
and
:checked
and
:selected
help you find radio buttons, select box items, and checkboxes that are checked or selected.
:checked
and :selected
in
Conditional Logicif($(this).is(':checked'))
.
val
function enough to know what
it does: it returns the value of a form field. We can now perform some
simple validation; let’s test to see if any text boxes in a form are
empty:
$('#myform').bind('submit', function(event) { $('[type=text]').each(function() { if(!$(this).val().length) { event.preventDefault(); $(this).css('border', '2px solid red'); } }); });
val
action works for
select boxes and radio buttons too. As an example, let’s
alert the radio button value when the user changes the selection:
This
change
event is fired whenever a
value in a form has changed. For a text input
or
textarea
, it fires
whenever a user changes the element’s value, but only when the focus is
moved away from the element. This is a great way to implement some
simple inline validation. For checkboxes, select boxes, and radio buttons, the change
event occurs
whenever the value changes from its current value. Mostly. In some
browsers, the change
event on a radio button is
triggered on click; in others, on a blur of the control, just like
input
s and textarea
s. You could
use a change
event and hope for the best, or you
could take our advice and opt to bind to the click that we know we can
trust.
Let’s revisit our simple validation example, except that
this time we’ll test for empty fields whenever the user moves to the
next field. For this, we’ll need to capture the
blur
event, which fires whenever a form
field loses focus. This is perfect for inline validation:
$(':input').blur(function() { if ($(this).val().length == 0) { $(this) .addClass('error') .after('This field must … '); } }); $(':input').focus(function() { $(this) .removeClass('error') .next('span') .remove(); });
required
as an attribute in a
compliant browser:<input value=”Jemima” placeholder=”Best new talent” required>Now there are two simple steps. First, wait for all browsers to support this feature, and second, wait for them all to implement an API for customizing the UI when a user receives feedback. Okay, maybe “simple” isn’t the word for it! Figure 7.2 shows the current state of play with browser validation. Of the big five, two offer no solution, and there’s a wide variation among those that do. And unless one of those UI options matches your site’s style, the only way to change how it looks is to turn it off. It’s safe to say that jQuery will be lending a hand with validation for quite a while, so let’s return to it.
submit
event, which
is fired when the form’s submitted. This is a better technique than
listening for a click event on the submit button, as it will also fire
if the user submits the form by pressing the Enter
key. Once again, we’re going to rely on our trusted
event.preventDefault
to ensure that the form will
only be submitted once we’re satisfied we have the required details in
our form. In our example following, we’ll check all the text boxes in
the form. If any are left empty, we’ll pop up a message and focus on the offending element:
$("form").submit(function(event){ var error = false; $(this).find("[type=text]").each(function(){ if (!$(this).val().length) { alert("Textboxes must have a value!"); $(this).focus(); error = true; return false; // Only exits the “each” loop } }); if (error) { event.preventDefault(); } });

Sign up
 <form action="">
 Name: <input name="name" id="name" type="text"/>

 Email: <input name="email" id="email" type="text"/>

 Web site URL: <input name="website" id="website" type="text" />

 Password: <input name="password" id="password" type="password" />

 Confirm Password: <input name="passconf" id="passconf" type="password" />
 <input type="submit" value="Submit!" /> </form>

validate
on a selection of our
form, passing it any options we want to use. The most important option
is
rules
, which is where you need to
define rules used to validate the users’ input:
$('#signup form').validate({ rules: { name: { required: true }, email: { required: true, email: true }, website: { url: true }, password: { minlength: 6, required: true }, passconf: { equalTo: "#password" } }, success: function(label) { label.text('OK!').addClass('valid'); } });
required
, email
,
url
, minlength
, and
equalTo
.
required
marks a field as required, so
it will be flagged as an error if it’s empty.
email
and
url
validate the format of the field;
emails must contain an @, URLs must begin with http://, and so on.
Inside the rules
object, we define an object for each
form field, using the field’s name
attribute.
minlength
is self-explanatory (and, as
you’d expect, there’s a corresponding
maxlength
). Finally,
equalTo
allows us to specify a jQuery
selector pointing at another form field, the contents of which will be checked against
the current field to see if they’re the same.
The Validation plugin will add a new label
element after each form field to contain
the
error message; by default, this will have a class
of error
, so you’re free to style it in as stern
a fashion as you’d like.
The plugin will only display a message if a field’s value is
invalid. User research has shown, however, that users complete forms
more quickly and confidently if they’re also provided with feedback for
correct entries. That’s why we’re using the
success
callback to set the value of the message
label
, and giving it a class
to style it with a nice green check
mark. success
is passed the message element
itself, so you can manipulate it in any way you’d like. Our sample form
is illustrated mid-completion in Figure 7.3.
It’s also possible to customize the error messages themselves, and
it’s worth noting that there are a number of localized variants in the
localization folder of the plugin
directory.
This example is just the beginning of what’s possible with the
Validation plugin. Make sure you consult the documentation and the
examples in the plugin’s demo folder to explore all the available
features. This is a powerful plugin with the sort of features that we
hope to see in the browser itself one day.
class
of maxlength
on the textarea
we want to target with this effect.
Then, in our script, we append a span
after it and add a new kind of event handler:
$('.maxlength') .after("") .next() .hide() .end() .keypress(function(event) { // handle key presses; });
textarea
is still the selected element. We
want to modify the new span
, so we
move to it with the next
action. Then we hide
the span
, but now we need to go back
to our form element to add an event handler, so we use the
end
action. The
end
action moves the jQuery selection back to
where it was before the last time you changed it. In our example,
hide
doesn’t change the
selection, but
next
does. So when we call
end
, the selection moves back to the state it
was in before we called next
.
Now that we’re back on the form element, we attach a
keypress
event handler. As you
might expect, this event fires whenever a key is pressed. Here we can
check whether another character is still allowed, and prevent the user
from adding more characters if it’s not:
var current = $(this).val().length; if (current >= 130) { if (event.which != 0 && event.which !== 8) { event.preventDefault(); } }
length
property to give us its
length. If the current number of characters is greater than the maximum
length, we’ll prevent the key press from registering by using the
preventDefault
action of the event.
When handling a keypress
event, the event has a
which
property corresponding to the
ASCII code of the key pressed. Note that we’ve allowed the
delete (ASCII code 0) and backspace
(ASCII code 8) keys to function regardless of the number of characters.
If we didn’t do this, the user could paste in a response that exceeded
the limit, yet be unable to delete any characters to make it
fit:
The last task to do is display the number of remaining characters
in the span
we created. We move to
the next element, make sure it’s visible, and display the results of our
simple calculation to indicate how many more characters are allowed. If
we liked, we could add a method to change the span’s style, making it
even easier to know when the 140-character cap is reached.
Our solution is, admittedly, a little draconian for something as
flippant as your average tweet, but it’s spot on if you want to limit
the number of characters in a credit card form, or even a software
license registration.
data
action, you’d be correct.
We’d love to be able to use the HTML5 placeholder
attribute, but we run into our usual support troubles here: there’s
still a considerable number of browsers that don’t support it, and those
that do require vendor-prefixed CSS to style it. So if we’re unable to
trust it being available in all browsers, you can see why we’re sticking
with data
. We’ll store the default value in
data
for each clearable item, and if the value
is still empty when the user leaves, we’ll restore it from there:
$('input.clear').each(function() { $(this) .data('default', $(this).val()) .addClass('inactive') .focus(function() { $(this).removeClass('inactive'); if($(this).val() === $(this).data('default') || ↵$(this).val() === '') { $(this).val(''); } }) .blur(function() { if($(this).val() === '') { $(this).addClass('inactive').val($(this).data('default')); } }); });
focus
and blur
events that will fire whenever the user
moves into or out of our input
s. On
focus
, we test if the value of the text
box is the same as our default text; if it is, we clear the box in
preparation for the user’s input.
On the way out, we check to see if the text box is empty, and if
it is we put the original value back in. We add and remove a class as we
go; this allows us to style the form fields differently when they’re
displaying the hint. In our example, we have simply made the text color
a little lighter.
We know that we’re using jQuery to take on some of the load that
HTML5 promises to shoulder, but the support just isn’t there
yet.

 Reason for Celebrity <input name="reason" type="checkbox" value="net" />Famous on the Internet
 <input name="reason" type="checkbox" value="crim" />Committed a crime
 <input name="reason" type="checkbox" value="model" />Dates a supermodel
 <input name="reason" type="checkbox" value="tv" />Hosts a TV show
 <input name="reason" type="checkbox" value="japan" />Big in Japan

 <input class="check-all" name="reason" type="checkbox" />Check all

class
of check-all
. This box will act as our master
checkbox: when it is checked or unchecked, our code springs to life.
First, we construct a selector string that will select all the
checkboxes with the same name as the master checkbox. This requires
gluing a few strings together, to end up creating a selector that looks like
:checkbox[name=reason]
.
We then set all the related checkboxes to have the same checked
value as our master checkbox. Because our code is running after the user
has changed the value, the
checked
property will reflect the new
state of the checkbox, causing all of the related items to be either
selected or deselected accordingly:
$('.check-all:checkbox').change(function() { var group = ':checkbox[name=' + $(this).attr('name') + ']'; $(group).attr('checked', $(this).attr('checked')); });
context
parameter of the jQuery
selector, as it limits where jQuery will hunt for your selections.
We’ll cover the context
parameter in Chapter 8.
p
tags and
title
tags, for example. When the
user clicks on the tag, the contents are replaced with a text box or
textarea
that the user can interact
with. When the task is complete, the original tags are replaced with the
new content.
We’ll use classes to mark content as being editable. For simple
one-liners, we’ll use input
elements
(by assigning the class editable
),
and for longer passages we’ll use textareas
(which we’ll give the class
name
editable-area
). We’ll also be sure
to assign each element a unique id
.
This is so we can send the data to the server for updating in the
database, and reload the new data on the next pageload:

Glendatronix

 When Glendatronix floated onto the scene with her incredible debut …

hover
event, which adds an effect that enables the
user to see that the element is editable (we’ll go with a
tried-and-tested yellow background color).
We also want to capture the click
event, which
fires when the user clicks on the editable content, and the
blur
event, which signifies the end of
editing:
$('.editable, .editable-area') .hover(function() { $(this).toggleClass('over-inline'); }) .click(function(event) { // Start the inline editing }).blur(function(event) { // End the inline editing });
$editable
variable (to prevent us having to reselect
it every time). We’ll also check for the active-inline
class
with
hasClass
. If the element already
has the active-inline
class
, it’s already an edit box. We’d rather
not replace the edit box with another edit box:
// Start the inline editing var $editable = $(this); if ($editable.hasClass('active-inline')) { return; }
html
data to a variable, but we’ll also use the
$.trim
method to remove
whitespace from the start and end of the content string.
This is necessary because, depending on how your HTML is laid out, the
string could have extra carriage returns and line spaces that we want to
prevent showing up in the text box. And as we’re sticklers for readable
markup, we take our code-cleaning one step further with our
replace
method. Our regular
expression looks for closing p
tags, and adds two new
line characters after them. When we edit an input
we won’t find any, but when we edit the
textarea
, our line breaks help to
space the code out nicely and make everything more readable. And as we
know, if it’s more readable, it’s more likely to be read!
Then we add our active
class
, which serves the dual
purpose of indicating that editing is in process, and providing a hook
for our styles. Finally, we clear out the current element with the
empty
action. This command is
similar to remove
, except that calling
empty
on an element will result in all its
children being removed, rather than
the element itself:
var contents = $.trim($editable.html().replace(/\/p>/g,"/p>\n\n")); $editable .addClass('active-inline') .empty();
empty
and
remove
remove
or
empty
command will be applied to the removed
selection, and not the selection that you had
before you removed the elements. The reasoning behind this is that if
you simply threw away the elements, they’d be lost forever. This way
you have the option to keep them around, process them, or store them
for future use.
textarea
. We’ll check for the editable
class
to determine what kind of form element
we need to append (remember that we indicated multiline content with
editable-area
). We then set the new
element’s value with the contents of the elements we removed, and append
it to the target element:
// Determine what kind of form element we need
var editElement = $editable.hasClass('editable') ?
↵'<input type="text" />' : '<textarea></textarea>';
// Replace the target with the form element
$(editElement)
.val(contents)
.appendTo($editable)
.focus()
.blur(function(event) {
$editable.trigger('blur');
});
trigger
function. It’s simply a
different way to cause an event to fire (so, in this example, we could also have
used the $editable.blur()
syntax we’ve already seen).
The trigger action is more flexible than its shorter counterpart, but
for now we’ll just stick with the basic usage.
trigger
is being used in this example for
clarity: to show whoever is reading the code that we want to manually
fire an event. In this case, we’re just passing on the event; the
input
was blurred, so we tell the
original element that it’s time to finish editing. We could manage all
this inside the input
box’s
blur
event handler, but by delegating the event, we
avoid nesting our code another level (which would make it harder to
read). It also makes sense to let the original element deal with its own
logic.
The counterpart to trigger
is
bind. bind
lets us add event
handlers to an object. Sound familiar? So far we’ve been binding events
by using shorthand convenience methods like
click
, hover
,
ready
, and so on. But if you pop the hood,
you’ll see that internally they all rely on
bind
.
The bind
action takes a string containing
the name of the event to bind, and a callback function to run. You can
also bind multiple events to an item in a single call by wrapping them
in an object. For example, our code attached three separate events to
.editable
and .editable-area
elements: click
, hover
, and
blur
. If you wanted to, you could rewrite that with
the bind
syntax:
$('.editable, .editable-area').bind({ hover: function(e) { // Hover event handler }, click: function(e) { // Click event handler }, blur: function(e) { // Blur event handler } });Let’s return to our example; with the editing over, we can go back to our default state. We’ll grab the value from the form element, and send it to the server with
$.post
, putting a
“Saving …” message in place as we do so. When the
POST
is done, we eliminate the message and replace it
with the updated value. As with the Ajax functionality we saw in the
previous chapter, we’re faking a server-side response with an empty
save file. In a real world application, you’d want
to check that the changes had actually been saved to the database by
checking the response data:
.blur(function(event) { // end the inline editing var $editable = $(this); var edited = $editable.find(':first-child').val(); $editable .children() .replaceWith('Saving … '); // post the new value to the server along with its ID $.post('save', {id: $editable.attr('id'), value: edited}, function(data) { $editable .removeClass('active-inline') .children() .replaceWith(edited); if ($editable.hasClass('editable-area')) { rapture($editable); } } ); });
replaceWith()
swaps whatever
you’ve selected with whatever you pass to it. Be careful when using it,
though; in our example, we know that our selector will only return one
collection, but if it returned multiple collections, each of those would
be replaced with the same loading message!
The last method we call is
rapture
, and we pass it the
$editable
parameter that we’ve been using. We wrap
the method call in an if
conditional to make sure we
only apply it to our edits to the textarea
content. Speaking of content, this
last method introduces us to our last new jQuery function for the
minute,
contents
:var rapture = function (which) { $(which).contents().filter(function() { return this.nodeType === 3; }) .wrap('

') .end() .filter('br') .remove() .end() .end() .children().filter(function() { $(this).html($.trim($(this).html().replace(/(\t|\n)/g,""))); return !$(this).text().length }).remove(); }
contents
method here.
contents
is similar to
children
in that the descendants
of an element are selected. The big difference is that the
children
method only collects elements, whereas
the contents
method collects all nodes—text
nodes as well as elements. This is useful in our editor, as we’re
unaware of the formatting for the copy added to the textarea
. It could be typed, or copied and
pasted—we don’t know. What are we to do?
Like the documentation, we’re going to filter each member of the
contents
collection. A
nodeType
of 3 means the node is text,
so we wrap those nodes in paragraph tags in order to manipulate them if
we need. Now we start some fun with the
end
method. Our first
end
sends us back to the
contents
collection, and we now
filter
the br
elements and
remove
them. We just talked about the
remove
method holding DOM items we’ve removed,
so we now need to call end
or our next chained
methods will be acted upon. And as we’re in the mood for a little
end
action, let’s call another to bring the
focus of our chain right back to the original
$(which)
collection.
Calling
children
now means we once again
have a collection of element nodes only, and not
all node types from our
$(which)
. That’s an important difference, and one to
look out for. Next, we filter
our child elements and
use the filtering method to help with cleaning our pasted content. Each
child element is given a trim
, and has any tab and
new-line special characters
replace
d with an empty string. The result is
well-formed, clean HTML, and when we then
remove
any empty p
elements,
our code is certainly fit to be saved.
We paste this: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.And it’s transformed to this:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Even better, by cleaning it and adding whitespace when we make the content editable, it’s fit to be edited. Okay, it may well have been easier for our client to have sourced the content through other channels, but now at least if a user needs to cut and paste in to our editable areas they’ll enjoy doing it!
class
es that are added. We’ve used several
of these styles to give our drop-down suggestion list a standard
appearance.
The Autocomplete plugin attaches itself to a select
box. We’re applying it to the location
field in our simple form:
Last known whereabouts: <input type="text" id="location"/>
var cities = ['Paris', 'New York', 'Milan', 'Stockholm' … ]; $('#location').autocomplete(cities,{ autoFill: true, selectFirst: true, width: '240px' });
autoFill
gives us a nice type-ahead
effect (filling out the text box with the currently suggested
completion), while
matchContains
will cause it to match
substrings of words, rather than just the first letters, and so on.
There’s a lot you can fine-tune, so it’s worth having a quick study of
the options list.
The plugin also fires the
result
event when the user chooses an
option. It will give us the name of the tag that was selected as the
second parameter passed to our event handler (after the event object).
For example, the following would alert the selected option when it’s
selected:
$('#location') .autocomplete(cities) .result(function(event, selection) { alert(selection); });Very simple, but very funky. And the client team are still playing with the last toy we built for them! Let’s use the time to swap our code using jQuery UI, like we said, and aim for Figure 7.6. Our first task is to make sure we have a version of jQuery UI that incorporates Autocomplete. That’s anything after 1.8, so we include it in our page as we’re used to doing. And that’s almost it! No HTML changes and no CSS changes; we just use the code from our plugin example. There are only minor changes to our code:
var cities = ['Paris', 'New York', 'Milan', 'Stockholm' … ]; $('#location').autocomplete({ source: cities });

 <input id="rating-1" name="rating" ↵type="radio" value="1"/>0.5 Stars <input id="rating-2" name="rating" ↵type="radio" value="2"/>1 Star <input id="rating-3" name="rating" ↵type="radio" value="3"/>1.5 Stars <input id="rating-4" name="rating" ↵type="radio" value="4"/>2 Stars <input id="rating-5" name="rating" ↵type="radio" value="5"/>2.5 Stars <input id="rating-6" name="rating" ↵type="radio" value="6"/>3 Stars <input id="rating-7" name="rating" ↵type="radio" value="7"/>3.5 Stars <input id="rating-8" name="rating" ↵type="radio" value="8"/>4 Stars

background-position
property:
.stars div a { background: transparent url(sprite_rate.png) 0 0 no-repeat; display: inline-block; height: 23px; width: 12px; text-indent: -999em; overflow: hidden; } .stars a.rating-right { background-position: 0 -23px; padding-right: 6px; } .stars a.rating-over { background-position: 0 -46px; } .stars a.rating-over.rating-right { background-position: 0 -69px; } .stars a.rating { background-position: 0 -92px; } .stars a.rating.rating-right { background-position: 0 -115px; }
createStars
function will take a container with radio buttons and replace it with
star links. Each star will then be supplemented with the proper event
handlers (in the
addHandlers
method) to let the
user interact with the control. Here’s the skeleton of our
starRating
object:
var starRating = { create: function(selector) { $(selector).each(function() { // Hide radio buttons and add star links }); }, addHandlers: function(item) { $(item).click(function(e) { // Handle star click }) .hover(function() { // Handle star hover over },function() { // Handle star hover out }); } }
create
method iterates through
each container matching the selector we pass in, and creates a list of
links that act as a proxy for the radio buttons. These links are what
we’ll style to look like stars. It will also hide the original form
elements, so the user only sees our lovely stars:
$(selector).each(function() {
var $list = $('

');
// loop over every radio button in each container
$(this)
.find('input:radio')
.each(function(i) {
var rating = $(this).parent().text();
var $item = $('')
.attr('title', rating)
.addClass(i % 2 == 1 ? 'rating-right' : '')
.text(rating);
starRating.addHandlers($item);
$list.append($item);
if ($(this).is(':checked')) {
$item.prevAll().andSelf().addClass('rating');
}
});
div
element); we’ll be creating one new link
for each of the radio buttons we’re replacing. After selecting all the
radio buttons with the
:radio
selector filter, we take each
item’s rating and use it to create a hyperlink element.
addClass
action, we’re
specifying the class name conditionally with a ternary operator (see the section called “Fading Slideshow
” in Chapter 4), based on a bit of math. As
we’ve done earlier in the book, we’re using the
modulus (%
) operator to determine
whether the index is even or odd. If the index is odd, we’ll add the
rating-right
class
; this makes the link look like the
right side of a star.
addHandlers
method; this is where we’ll attach
the events it needs to work. Then we append it to the list container.
Once it’s in the container, we see if the current radio button is
selected (we use the
:checked
form filter). If it’s checked,
we want to add the rating
class
to this half-star, and to all the
half-stars before it. Any link with the rating
class
attached will be assigned the gold
star image, allowing users to see the current rating.
To select all the elements we need to turn gold, we’re going to
enlist the help of a couple of new jQuery actions:
prevAll
and
andSelf
. The prevAll
action selects every sibling before the current
selection (unlike the prev
action, which only
selects the immediately previous sibling). For our example, we want to
add the class
to the previous
siblings and the current selection. To do so, we
apply the
andSelf
action, which simply
includes the original selection in the current selection. Now we have
all the links that will be gold, so we can add the class
.
prevAll
, jQuery provides us with a
nextAll
method, which grabs all
of an element’s siblings occurring after it in
the same container. jQuery 1.4 introduced two new companion methods:
prevUntil
and
nextUntil
. These are called
with a selector, and will scan an element’s siblings (forwards or
backwards, depending on which one you’re using) until they hit an
element that matches the selector.
So, for example,
$('h2:first').nextUntil('h2');
will give you all
the elements sitting between the first h2
on the page and the following h2
in the same container element.
If you pass a second parameter to
prevUntil
or
nextUntil
, it will be used as a selector to
filter the returned elements. So, for example, if we had written
nextUntil('h2', 'div')
, it
would only return div
elements
between our current selection and the next h2
.
// Hide the original radio buttons $(this).append($list).find('label').hide();
$(item).click(function(e) { // Handle star click }) .hover(function() { $(this).prevAll().andSelf().addClass('rating-over'); },function() { $(this).siblings().andSelf().removeClass('rating-over'); });
hover
function is the easiest: when
hovering over, we select all the half-stars before—including the current
half-star—and give them the rating-over
class
using prevAll
and andSelf
, just like we did in the setup.
When hovering out, we cover our bases and remove the rating-over
class from all the links. That’s
hovering taken care of.
Now for the click:
// Handle Star click
var $star = $(this);
var $allLinks = $(this).parent();
// Set the radio button value
$allLinks
.parent()
.find('input:radio[value=' + $star.text() + ']')
.attr('checked', true);
// Set the ratings
$allLinks.children().removeClass('rating');
$star.prevAll().andSelf().addClass('rating');
// prevent default link click
e.preventDefault();
click
event
is to update the underlying radio button model. We do this by selecting
the correct radio button with the
:radio
filter and an attribute
selector, which searches for the radio button whose value matches the
current link’s text.
With the model updated, we can return to messing around
with the CSS sprites. First, we clear the rating
class
from any links that currently have it,
then add it to all the links on and before the one the user selected.
The last touch is to cancel the link’s default action, so that clicking
the star doesn’t cause it to fire a location change.
<fieldset id="radio"> <input type="radio" id="radio1" name="radio" />Find a celebrity <input type="radio" id="radio2" name="radio" checked="checked" ↵/>Report a celebrity <input type="radio" id="radio3" name="radio" />Become a celebrity </fieldset>
$("#date").datepicker();The date picker is triggered when the
input
box receives focus
,
and slides into view with the current month and day selected. When the
text box loses focus
, or when a date is selected, it
disappears. Sure, it looks very nice, and works with the jQuery
smoothness we expect—but what does it offer us over and beyond competing
date pickers? (Remember, just because you’re using jQuery, it doesn’t
mean you should ignore other suitable JavaScript components, or even
HTML5.)
The date picker component in jQuery UI is feature-packed. Packed!
It is fully localizable, can handle any date formats, lets you display
multiple months at once, has a nifty date range mechanism, allows
configurable buttons, is keyboard navigable (you can move around with
ctrl + arrow keys), and more.
All told, there are over 50 options and events available to you to
tweak—almost every tiny aspect of the date picker! To make the calendar
you see in Figure 7.10, we’ve used just a few of
them:
$('#date').datepicker({ showOn: 'both', buttonText: 'Choose a date', buttonImage: 'calendar.png', buttonImageOnly: true, numberOfMonths: 2, maxDate: '0d', minDate: '-1m', showButtonPanel: true });
showOn
lets us choose when the
calendar will pop up. The available options are
'focus'
(when the text box receives focus),
'button'
(a button is added next to the text box,
which users can click to open the calendar), or
'both'
(which allows for both options). To use an
icon for the button, we’ve specified a
buttonImage
. We also set
buttonImageOnly
to
true
; this means that only the image will be
displayed, rather than a standard form button
.
Next up, we’ve set the
numberOfMonths
to 2
;
this means the user will see two months’ worth of days at the same time.
You can even specify an array instead of an integer; for example,
[3, 3]
will show a 3x3 grid of months!
The
maxDate
and
minDate
options let you set the range
within which the user can select a date. You can specify a JavaScript
date object, or you can use a string to dictate relative dates. The
latter option is usually easier, and that’s what we’ve done here. We’ve
set the maxDate
as 0, which stands for today’s date.
The minDate
we’ve set as -1m -1w; this means that the
user can only select a date that is up to one month and one week in the
past. You can plus or minus as much time as you need:
y
for year, m
for month,
w
for week, and d
for day.
Again, many of the options for our date picker will someday be
championed by our browsers and HTML5, but we’re not quite there yet. So
again, familiarize yourself with HTML5 and investigate a shim (software
that implements a compatibility workaround) to bolster older browser
support, but be comfortable knowing that what you learn about jQuery and
JavaScript here will be useful to you for quite a wee while.
$.datepicker.setDefaults
method
accepts an object made up of date picker settings. Any settings that
you specify will be applied to all date pickers on the page, unless
you manually override the defaults. For example, if you want every
date picker to show two months at a time:
$.datepicker.setDefaults({ numberOfMonths: 2 });The remaining utility functions are for manipulating or assisting with dates and date formats. The
$.datepicker.iso8601Week
function accepts a date and returns the week of the year it’s in, from
1 to 53. The
$.datepicker.parseDate
function
extracts a date from a given string; you need to pass it a string and
a date format (for example, "mm-dd-yy"
), and you’ll
receive a JavaScript date object back. Finally, the
$.datepicker.formatDate
does
the opposite. It will format a date object based according to the
format you specify—great for displaying dates on screen.
slider
!
We’ll start with a basic form, consisting of two select
boxes: one for the maximum price, and
one for the minimum price. Then we’ll call on jQuery UI to add a fancy
slider to control the values of those boxes. The end result is
illustrated in Figure 7.11.
Let’s have a look at the basic markup:

 <form action=""> <fieldset> Minimum Price: <select id="min" name="min"> <option value="0">0</option> <option value="10">10</option> <option value="20">20</option> … <option value="80">80</option> <option value="90">90</option> </select>
 Maximum Price: <select id="max" name-"max"> <option value="10">10</option> <option value="20">20</option> <option value="30">30</option> … <option value="100">100</option> </select> </fieldset> </form>

select
boxes. Then we initiate our slider by
calling the slider
method on a newly created
empty div
:
var max = $('#max').val(); var min = $('#min').val(); var rangeSlider = $('

') .slider({ min: 0, max: 100, step: 10, values: [min, max], range: true, animate: true, slide: function(e,ui) { $(this) .parent() .find('#min') .val(ui.values[0]); $(this) .parent() .find('#max') .val(ui.values[1]); showCelebs(); } }) .before('
Drag the slider to filter by price:
'); $('#price-range').after(rangeSlider).hide();
min
and
max
are the minimum and maximum values
of the slider, respectively. step
is the amount by
which the slider increments.
values
is used for specifying the
default value of the slider. Because we’ve specified an array of two
values, the slider bar will have two handles, each with a separate
value. Here we’re using the values from the select
lists that we grabbed earlier, so that
the slider will always match up with the data in those boxes.
range
and
animate
are helpful options when
creating a slider with more than one handle, as we’re doing here:
range
indicates that the area between the handles
should be styled differently, usually with a shadow or a different
color. This option can also be set to min
(in which
case the area between the minimum and the first handle will be shaded)
or max
(which will shade the area between the last
handle and the maximum). animate
simply tells jQuery
to animate the handle’s position smoothly if the user clicks elsewhere
on the bar, rather than simply jumping there.
Finally,
slide
allows you to specify an event
handler that will run whenever the user moves the handles on the slider.
The event handler can accept an optional ui
parameter
that allows you to access some of the slider’s properties; here we’re
using the values
property to adjust the values of
our select boxes. We also call showCelebs
, a
custom method in which we’ll show or hide celebrities, depending on
whether their prices fall within the chosen range.
It’s also possible to capture the change
event,
which is very similar to the slide
event except that
it will also fire if the slider’s values are modified programmatically
(slide
only fires when the user interacts directly
with the slider).
The jQuery UI slider component will create a horizontal slider by
default—but if you want a vertical one you can specify
orientation: 'vertical'
.
We’ve used before
and
after
to add a title to our slider and affix it
to the page, and we’ve also hidden the original select
boxes. Try this now, and you’ll see a
nicely themed slider that you can play with, and which will adjust the
values of the select
boxes.
In order to make it filter the celebrities, we simply need to
implement the showCelebs
method:
function showCelebs() { min = $('#min').val(); max = $('#max').val(); $('.data tr').each(function() { var price = parseInt($(this).find('td:last').text(). ↵substring(1)); if (price >= min && price <= max) { $(this).fadeIn(); } else { $(this).fadeOut(); } }); }
substring(1)
to extract everything from
the first character on (which will conveniently strip the prices of
their dollar signs). Then we use
parseInt
to turn the string into
a number.
We’ll also call showCelebs
on
document-ready, so that the list is prefiltered based on the default
values in the form.
This works as expected, and allows users to visually filter
celebrities based on their desired price range. Sliders are a great UI
widget because they’re so intuitive: users will know how to use them
without being told. You can probably come up with a few other controls
that could benefit from being sliderized!
img
tags. You can choose any
type of element to be draggable, just as long as you can make it look
pretty and work well for your users. A nice touch is to set
cursor: move
on the draggable elements;
that way, users will see the “grabby hand” icon and know they can drag
it.
As always, we’ll start with the markup:

  Drag images here to delete

.trash
div
in
the markup here. However, this poses a problem for users with
JavaScript disabled; they’ll see a trash area, but will be unable to
do anything with it! In a real-world app, you’d want to start with a
fully functional, HTML form-based interface for deleting images (or
whatever it is you intend to use drag and drop for). Then you’d use
all the methods we’ve seen throughout the book to remove those
interface elements from the page, and replace them with the above
drag-and-drop markup.
draggable
and
droppable
—to handle smooth
cross-browser drag and drop.
draggable
and
droppable
are behaviors, with no preset
styling necessary. They do, however, give you some quite handy
class
names to apply your own
styles to, which we’ll look at shortly.
$(document).ready(function() { $('#photo-grid > img').draggable({ revert: 'invalid' }); $('.trash').droppable({ activeClass: 'highlight', hoverClass: 'highlight-accept', drop: function(event, ui) { puffRemove($(ui.draggable)); } }); }); function puffRemove(which) { // Implement the “puff-of-smoke” effect }
draggable
interaction helper makes
whatever you select draggable with the mouse. Try this out for size:
$('p').draggable()
. It can make every

tag on the page draggable. Test it
out—it’s a lot of fun. Naturally, there are stacks of options and
events to customize the behavior. Here are some of the more helpful
ones:$('p').draggable({axis: 'y', containment: 'parent'});The
axis
option restricts the object to
be draggable along either the X or Y axis only, and the
containment
option confines the
object to a bounding box; acceptable values are
'parent'
, 'document'
, and
'window'
(to stay within the respective DOM
elements), or an array of values to specify pixel boundaries in the
form [x1, y1, x2, y2]
. You can also use the
grid
option to confine dragging to a
grid, by specifying a two-element array (for example,
grid:[20,20]
).
Let’s look at another example:
$('#dragIt').draggable({ handle: 'p:first', opacity: 0.5, helper: 'clone' });For this next bunch of options, we’re operating on a
div
called dragIt
, which contains at least one

tag. We use the
handle
option to designate the first
p
element as the “handle” users can
use to drag the draggable element around. We also specify the
helper
option, which allows you to
specify an element to represent the node being dragged around. In this
case, we’ve set this option to
clone
. This causes the element to be
duplicated, so that the original element will stay in place until
you’ve finished dragging. The opacity
applies to
the helper element.
The other option worth noting is
revert
. If you set this to
invalid
(as we did in our photo-dragging example),
the element you drag will spring back to its original position if you
drop it outside of a droppable target area.
There are also three events you can catch—
start
,
stop
, and
drag
—that fire when you start
dragging, stop dragging, and are in mid-drag, respectively. In our
example we only need to react to drop, but you can easily conceive of
situations where the other two events could be put to good
use.
draggable
’s Clyde is the
droppable
behavior. Droppable elements are
targets for draggable items. A droppable element has far fewer options
than a draggable element; we’ve used the most important,
activeClass
and
hoverClass
, in the earlier example.
The activeClass
is added to the droppable element
when a draggable item is being dragged. Similarly, the
hoverClass
is added when a draggable item is
hovering over the droppable element.
You can also specify a selector for the
accept
option, which restricts the
draggables that can be dropped. This lets you have multiple drop
points, where only certain draggable items can go. This can be great
for list manipulation.
The events for a droppable element are similar to draggables.
Instead of start
, stop
, and
drag
, we have
over
,
out
, and
drop
. In our photo grid example,
we’ve used the drop
event to know when to destroy
the draggable item.
Both the draggable
and
droppable
behaviors are complex beasts. Once you’re
over the thrill of how easy they are to implement, you should have a
further read through the advanced options in the documentation.
Actually, a little birdie—and no, not that blue one—has
let slip that in jQuery UI 2.0, we can expect some changes to the way
drag and drop works. However, the API should stay true to form, with
the options merely being tweaked, and the behind-the-scenes code
receiving the lion’s share of the attention. Your existing code should
continue to work trouble-free, but we know you’re going to want to go
back and add in some of those new options!
animate
function, we’ll need to roll our own
animation solution. This is because we need to cycle through image
frames, like creating cartoons. To do this, we’ll use a PNG image that
has five same-sized frames of animation all stacked on top of each
other, and then offset the image to show the correct frame. This means
we’ll need to change the position of the image in discrete chunks. If
we were to use animate
instead, it would
change the background position gradually, resulting in chopped-off
images halfway between frames:
// Implement the “puff-of-smoke” effect var $this = $(which), image_width = 128, scale_factor = $this.outerWidth() / image_width, frame_count = 5, $trash, $puff;
image_width
is the width in pixels
of the animation image. The frame_count
is the
total number of frames in the animation (the total height of the
image, therefore, should be image_width *
frame_count
). Of course, these will always be the same in
our example, but this way, if you ever want to use a different
animation image, you can find the numbers you need to change right at
the top of the script, instead of hunting through it to change them in
multiple places.
We then set up a container to house the image. The container
will be exactly the same size, and in exactly the same place as the
element we’re deleting:
// Create container $trash = $('

') .css({ height: $this.outerHeight(), left: $this.offset().left, top: $this.offset().top, width: $this.outerWidth(), position: 'absolute', overflow: 'hidden' }) .appendTo('body');
overflow
set to
hidden
, only a single frame of the image will ever
be seen:
$puff = $('') .css({ width: image_width * scale_factor, height: (frame_count * image_width) * scale_factor }) .data('count', frame_count) .appendTo($trash);
$('');
.
This will load the image without displaying it, so it will be ready
for your animation.
count
property to the image via the
data
action. This contains the total number
of frames left to show. With all of this in place, we can go ahead and
delete the original element that was dropped:
// Remove the original element $this.animate({ opacity: 0 }, 'fast').remove();
animate
method, rather than the more succinct
fadeOut
, as the timing is different. We left
both methods in the example code with one commented out. Why not run a
few tests for yourself? From where we sit, the animation using
fadeOut
starts later, where using two
animate
methods allows them to seem more like
one process. Now let’s check on that second
animate
.
While our dropped image is fading out, we want to initiate the
animation. This is going to require a small amount of JavaScript-fu.
We will set up a self-contained, self-executing
loop that plays the animation through once:
// Animate the puff of smoke (function animate() {(1) var count = $puff.data('count');(2) if (count) {(3) var top = frame_count - count; var height = $puff.height() / frame_count; $puff.css({ "top": - (top * height), 'position': 'absolute' }); $trash.css({ 'height': height }) $puff.data("count", count - 1);(4) setTimeout(animate, 75);(5) } else { $puff.parent().remove();(6) } })();
sortable
behavior. An element that you declare
as sortable
becomes a droppable target to its
children, and the children all become draggable. The result is that you
can reorder the children as you see fit. While sortable allows us to
order items within a container, it doesn’t actually sort anything: the
sorting is up to the user.
This makes it perfect for lists of elements where order needs to
be managed. Rather than using the fiddly move up the
list or move down the list buttons
that we usually see next to lists, we can apply the
sortable
behavior to them and allow our users
to reorder the list in a more intuitive way.
On the front page of StarTrackr! there are two lists that show the
ranking of the week’s top celebrities. One is for the A-list
celebrities, and the other for the B-list. This is the perfect
opportunity to show our client a cool trick: making the lists
reorderable by the users. They can move the celebs up and down the
lists, and even swap them if they challenge their A/B list status. When
they’re happy with their reordering, they can click the
Accept button and the changes will be submitted
to the server.
Lists are the primary targets for the
sortable
behavior. With a little extra work, a
div
can also take up the challenge.
For this example, we’ll use the following markup:

Glendatronix

Baron von Jovi
 …

Mr Speaker
 …

draggable
and
droppable
, making an element
sortable
is straightforward:
$("#a-list, #b-list").sortable();There’s a raft of methods, events, and options that are available when an element becomes
sortable
, and we can
combine them to control the interesting moments that occur during the
course of the sorting:
$("#a-list, #b-list").sortable({ connectWith: '.connected', placeholder: 'ui-state-highlight', receive: function(event, ui) { adopt(this) }, remove: function(event, ui) { orphan(this) } }).disableSelection();
sortable
s, and we’ll build on those methods to
make our actions a little more user-friendly. A nice touch we can
exploit is that accessing this
inside the callbacks
(as we’ve done above) gives us a reference to the
sortable
element.
disableSelection
sortable
instantiation is a nifty action:
disableSelection
.
disableSelection
, and its reverse,
enableSelection
, are two really
powerful methods in the jQuery UI. Calling
disableSelection
makes it impossible for
users to select text inside the target elements. It can be used to
stop text from being selected when users are dragging—or sorting—the
element, and prevents users from accidentally highlighting text when
they just want to drag an item.
Keep your eye on these methods: there’s much in store for them
in UI 2.0!
function adopt(which) { if ($(which).hasClass('empty')) { $(which).removeClass('empty').find('.empty').remove(); } } function orphan(which) { if ($(which).children().length == 0) { $(which) .append($('
empty
')) .addClass('empty'); } }
empty
to a list when its last item is
removed, and remove the text as soon as a new item is added. The
receive
event is fired when a sortable
list receives an item from a connected list. We use it to call our
custom adopt
method, wherein we remove the
“empty” text if it’s found.
Removing a child from a sortable
fires
the remove
event, which we use to call our
orphan
function. This method checks to see if
the parent sortable
has no children. Should it
be empty, we give it a child

and
assign it the empty
class
.
div
:
<form action=""> <fieldset> <legend>StarChirp</legend> <textarea id="chirper" rows="10" cols="50"></textarea>

0

 <button type="submit">Chirp!</button> </fieldset> </form>
$('#bar').progressbar({value:
50})
.
For our StarChirp box, we’ll monitor the user’s key presses in
much the same manner as we did for the maximum length indicator earlier
in this chapter. This time, however, we need to update the progress bar
as the user types:
$('#chirper') .val('') .keyup(function(e) { var characters = 140; var chirp = $('#chirper').val(); var count = chirp.length; if (count <= characters) { $('#bar').progressbar('value', (count / characters) * 100); $('#count').text(count); } else { $('#chirper').val(chirp.substring(0,characters)); } });
value
option.
If there are already more characters in the box than what’s
allowed, we’ll use the JavaScript substring
function to chop off the excess.
The effect is that every character we add will move the progress
bar to the right, and every character we remove will move the progress
bar to the left.
div
. When we want to show it, we’ll
copy the contents into the dialog structure and fade it in. That way we
can have multiple dialogs that use the same lightbox elements:

End User License Agreement
 …
 Agree Disagree

#overlay { bottom: 0; display:none; left: 0; margin-right: auto; margin-left: auto; position: fixed; right: 0; top: 0; width: 100%; z-index: 100; } #blanket { background-color: black; bottom: 0; display: block; opacity: 0.8; position: absolute; top: 0; width: 100%; } .dialog { background: white; border-radius: 10px; display: none; margin: 100px auto; position: relative; width: 500px; padding: 40px; }
openDialog
function that will be responsible
for taking the dialog HTML, transporting it to the overlay structure and
displaying it. The “transporting” part is achieved via the
clone
action, which creates a
copy of the current jQuery selection, leaving the original in place.
When we close the dialog we’re going to remove the contents, so unless
we cloned it each time, we’d only be able to open it once:
function openDialog(selector) { $(selector) .clone() .appendTo('#overlay') .show() .parent() .fadeIn('fast'); }
$("#eulaOpen").click(function() { openDialog("#eula"); });
function closeDialog(selector) { $(selector) .parents("#overlay") .fadeOut('fast', function() { $(this) .find('.dialog') .remove(); }); }
closeDialog
function
from within the current dialog. But as well as closing it, the buttons
in a dialog should have other effects. By adding extra buttons in the
dialog’s HTML, and hooking onto them in the document-ready part of your
code, you can run any arbitrary number of event handlers and process
them as you need:
$('#eula') .find('.ok, .cancel') .on('click', function() { closeDialog(this); }) .end() .find('.ok') .on('click', function() { // Clicked Agree! }) .end() .find('.cancel') .on('click', function() { // Clicked disagree! });
on
action. When we use
clone
to duplicate a DOM node, its event handlers get lost in the process, but
on
keeps everything in place no matter how
often we clone and delete nodes!
This is a simple but fairly crude way to handle the button events.
In Chapter 9, we’ll look at how we can set up
a custom event-handling system. The advantage of the method used here is
that it’s extremely lightweight and targeted to our particular needs.
But manually creating buttons and handling the related events would
quickly become tiring if you have many complicated dialogs to look
after, so you’ll probably be interested in the jQuery UI Dialog
widget.

You've assigned the current celebrity a rating of 0 …

Perhaps you are just judging them on the terrible last ↵ movie …

title
attribute specifies the text
to be displayed in the title bar of the dialog. Other than that, there’s
little going on in our HTML … so where do those buttons come from? Let’s
have a look at the script:
$('#dialog').dialog({ autoOpen: false, height: 280, modal: true, resizable: false, buttons: { Continue: function() { $(this).dialog('close'); // Submit Rating }, 'Change Rating': function() { $(this).dialog('close'); // Update Rating } } });
dialog
function.
The buttons are grouped together in an object and assigned to the
buttons
property of the dialog. To
define a button, you need to create a named function inside the
buttons
object. The function code will execute
whenever the user clicks the button, and the name of the function is the
text that will be displayed on the button. If you want your button text
to contain a space, you’ll need to wrap the function name in quotes. The
buttons are added to the dialog from right to left, so make sure you add
them in the order you want them displayed. This is quite a neat way to
package together the button functions with the dialog, unlike our custom
dialog where the functionality was specified independently of the dialog
code.
autoOpen
property to false
. Now,
when the page is loaded, the dialog sits and waits for further
instructions.
When the user clicks the rating-0
link, we tell the dialog to display
itself by passing the string
'open'
to the
dialog
method. This is a good way to
communicate with the dialog after the initialization phase:
$('#rating-0').click(function() { $('#dialog').dialog('open'); });
$(this).dialog('close')
. As you might suspect, the
close
command is the opposite of the
open
command. You can open and close the dialogs as
many times as you need.
What else can the plugin do? Well, we’ve specified the option
modal
to be true
,
that’s why we have the nice stripey background; but by default,
modal
will be false
, which allows
the user to continue working with the rest of the page while the dialog
is open. Additionally, we’ve set
resizable
to false
(and left the
draggable
option on default, which is
true
). These options make use of the jQuery UI
resizable
and draggable
behaviors
to add some desktop flavor to the dialog.
We specified the dialog’s title text in HTML, but you can also do
it in jQuery via the
title
property, just as you can set its
width and height. One less obvious, but extremely useful alternative is
the bgiframe
(background iframe) option.
If this option is set to true
, the bgiframe plugin
will be used to fix an issue in Internet
Explorer 6 where select boxes show on top of other elements.
In terms of events, you can utilize the dialog’s
open
,
close
, and
focus
events if you need to do some
processing unrelated to buttons. But there’s also an extremely useful
beforeClose
event that occurs when a
dialog is asked to close—before it actually does! This is a great place
to handle any processes you’d have to do regardless of which button was
clicked. It’s also useful if you need to stop the dialog from closing
unless certain conditions are satisfied.
By now, you’re starting to appreciate the depth of the jQuery UI
library. All the controls are well thought-out and feature-rich. As
always, you need to weigh the leaner custom option against the more
bandwidth-intensive (but quick to implement and more fully featured)
jQuery UI alternative. Which one you choose should depend on your
project requirements.
#growl { position: absolute; bottom: 0; right: 5px; width: 320px; z-index: 10; }
function addNotice(notice) { $('

') .append('

') .append('close') .append($('

').html(notice)) .hide() .appendTo('#growl') .fadeIn(1000); }
div
available for styling
(we’re using it to lay the visible message over a semiopaque
background), a close button, and a container for the message
contents.
One other point to note about this function is that any HTML we
pass to it is wrapped in the jQuery dollar selector. This means we can
pass in either plain text, HTML, or jQuery objects, and they’ll be
displayed in the box. You can style it however suits your site, though
you’ll need to give the bubble container position:
relative
:
.notice { position: relative; min-height: 30px; } .skin { position: absolute; background-color: #000000; bottom: 0; left: 0; opacity: 0.6; right: 0; top: 0; z-index: -1; -moz-border-radius: 5px; -webkit-border-radius: 5px; } .close { background: transparent url('button-close.png') 0 0 no-repeat; text-indent: -9999px; position: absolute; top: 2px; right: 2px; width: 26px; height: 26px; }
addNotice
function with a message, and it will
fade in at the bottom of the screen:
addNotice("
Welcome to StarTrackr!
"); setTimeout(function() { addNotice('
Stay awhile!

Stay FOREVER!
'); }, 1000);
addNotice
whenever you want to display a
message to the user. The only problem is … once the bubbles are there,
they’re unable to be removed—they just keep stacking up! Let’s fix
this:
$('#growl') .find('.close') .on('click', function() { // Remove the bubble });
click
handler directly to
the close button, we’re using the
on
function to keep an eye on any
new .close
elements that are added. This helps us
separate out the closing code and keep everything nice and readable. All
that’s left to do now is handle the actual removing:
// Remove the bubble $(this) .closest('.notice') .animate({ border: 'none', height: 0, marginBottom: 0, marginTop: '-6px', opacity: 0, paddingBottom: 0, paddingTop: 0, queue: false }, 1000, function() { $(this).remove(); });
closest
action, and animates it
to invisibility in an appealing way. Once it’s invisible, the container
is no longer needed, so we remove it from the DOM. The
closest
method is another one of jQuery’s DOM
traversing actions, and has the cool ability to locate the closest
parent element that matches the selector you give it, including
itself.
Add to wishlist
class
adding
, so let’s make sure that when we
append them, they’ll be invisible and properly located:
.adding { position:relative; left:-35px; top:-4px; display:none; }
wishlist
class
) is clicked, we call a custom function
that sets our notification in motion. The custom function takes a
reference to the current object and a callback function to run when the
interaction is complete. This function will move the selection to the
link (via the
prev
action) and set its text to
Added:
$('Adding')
.addClass('adding')
.insertAfter('.wishlist');
$('.wishlist')
.click(function(e) {
doOneUp(this, function() {
$(this).prev().text('Added');
});
e.preventDefault();
})
span
element and displays it. Now the message is visible to the end user. We
then kick off an animation that adjusts the span
’s top
and
opacity
properties, so as to move it upwards and
fade it out simultaneously:
function doOneUp(which, callback) { $(which) .next() .show() .animate({ top:"-=50px", opacity:"toggle" }, 1000, function() { $(this) .css({top: ""}) .hide('slow', callback) .remove(); }); }
callback
variable that’s
being passed around in the example? We supply a function as a
parameter to our doOneUp
code, but we don’t
do anything with it ourselves; we just pass it along as the callback
to jQuery’s
hide
action. When
hide
completes, it will run whatever code we
gave it. In this case, it’s the code to change the link text from
Add to wishlist to
Added.


Here's the recent weather on Mars:
Yesterday:
Two days ago:
Three days ago:
Four days ago:
Five days ago:
Six days ago:
Seven days ago:
Here's the most recent photo sent back from the Curiosity Rover on Mars
Here's the most recent photo sent back from the Opportunity Rover on Mars
Here's the most recent photo sent back from the Spirit Rover on Mars


Contact Form
Please fill all the texts in the fields.
Your name:
Your Email:
Message:
Subject:
Job Inquiry
General Question
Send


1
2
3
Generated Time Table
| Theory Hours |
8.00AM-8.50AM |
9.00AM-9.50AM |
10.00AM-10.50AM |
11.00AM-11.50AM |
12.00AM-12.50AM |
|
|
2.00PM-2.50PM |
3.00PM-3.50PM |
4.00PM-4.50PM |
5.00PM-5.50PM |
6.00PM-6.50PM |
7.00PM-7.50PM |
| Lab Hours |
8.00AM-8.45AM |
8.46AM-9.30AM |
10.00AM-10.45AM |
10.46AM-11.30AM |
11.31AM-12.15AM |
12.16AM-1.00PM |
|
2.00PM-2.45PM |
2.46PM-3.30PM |
4.00PM-4.45PM |
4.46PM-5.30PM |
5.31PM-6.15PM |
6.16PM-7.00PM |
| Monday |
A1/L1 |
F1/L2 |
D1/L3 |
TB1/L4 |
TG1/L5 |
L6 |
L |
A2/L31 |
F2/L32 |
D2/L33 |
TB2/L34 |
TG2/L35 |
V3/L36 |
| Tuesday |
B1/L7 |
G1/L8 |
E1/L9 |
TC1/L10 |
TAA1/L11 |
L12 |
U |
B2/L37 |
G2/L38 |
E2/L39 |
TC2/L40 |
TAA2/L41 |
V4/L42 |
| Wednesday |
C1/L13 |
A1/L14 |
F1/L15 |
V1/L16 |
V2 |
|
N |
C2/L43 |
A2/L44 |
F2/L45 |
TD2/L46 |
TBB2/L47 |
V5/L48 |
| Thursday |
D1/L19 |
B1/L20 |
G1/L21 |
TE1/L22 |
TCC1/L23 |
L24 |
C |
D2/L49 |
B2/L50 |
G2/L51 |
TE2/L52 |
TCC2/L53 |
V6/L54 |
| Friday |
E1/L25 |
C1/L26 |
TA1/L27 |
TF1/L28 |
TD1/L29 |
L30 |
H |
E2/L55 |
C2/L56 |
TA2/L57 |
TF2/L58 |
TDD2/L59 |
V7/L60 |
| Code |
Subject |
Teacher |
Credits |
| ### |
A |
Hemsworth |
1 |
| ### |
B |
Wilson |
1 |
| ### |
C |
Dooley |
1 |
|
|
|
Total |


The best way to understand how to write a custom theme is to look at the files from a running example. To look at the files used to create one of the custom themes available in this demo first pick a custom theme. For example, pick 'green' or 'stealth' .
For details about theming please see the theming developer guide chapter.
The "settings" file has a commented version of the platform theme variables. To see how to use it to customize values please follow the directions above to see a tutorial.
File (read only view):
The next steps show you the scss files for the currently selected custom theme, but first here's some background information.
In the next steps we'll see the content of the settings file, however please note that you can use JET tooling to scaffold up all the relevant files, see the tooling section of the theming developer guide chapter for more information.
File: src/
Here you can see the customized variables for the '
File: src/
In the previous step you saw the actual settings file for the '
File (read only view):


Why a file server?
One of the most common ways to network Linux and Windows computers is to configure Samba as a File Server. This section covers setting up a Samba server to share files with Windows clients.
 To do this server, I’m using a Fedora 33 server OS. Let’s start by installing the packages needed to make our server a Samba file server.
Install requirements
The packages needed are Kerberos, Samba and WinBind:
# dnf install krb5-workstation.x86_64 samba-winbind samba-winbind-clients samba samba-client
Configure Kerberos
Now let’s configure Kerberos with the correct domain, in this case, test.local and its domain controllers:
# vim /etc/krb5.conf
[libdefaults]
default_realm = TEST.LOCAL
[realms]
TEST.LOCAL = {
kdc = domaincontroller1.test.local
kdc = domaincontroller2.test.local
admin_server = domaincontroller1.test.local
}
[domain_realm]
.test.local = TEST.LOCAL
test.local = TEST.LOCAL
Now, test a user credential (my user is arthur):
$ kinit<EMAIL_ADDRESS>Password for<EMAIL_ADDRESS>$ klist -v
Credentials cache: API:501:9
Principal<EMAIL_ADDRESS>Cache version: 0
Server<EMAIL_ADDRESS>Client<EMAIL_ADDRESS>Ticket etype: aes128-cts-hmac-sha1-96
Ticket length: 256
Auth time: Apr 30 16:11:36 2021
End time: Apr 30 02:11:22 2021
Renew till: Apr 30 16:11:36 2021
Ticket flags: pre-authent, initial, renewable, forwardable
Addresses: addressless
Configure WinBind
Now let’s configure Winbind so that you can login with the domain users just configured in kerberos. Edit the file below and look for the three lines and replace them with the values described here
# vim /etc/nsswitch.conf
...
passwd: files winbind
group: files winbind
shadow: files winbind
...
Configure Samba share
Once Kerberos is configured to communicate with your domain controllers, let’s configure Samba.
# vim /etc/samba/smb.conf
[global]
# No .tld
workgroup = TEST
# Active Directory System
security = ads
# With .tld
realm = TEST.LOCAL
password server = domaincontroller1.test.local
wins support = yes
# Just a member server
domain master = no
local master = no
preferred master = no
# Disable printing error log messages when CUPS is not installed.
printcap name = /etc/printcap
load printers = no
# Works both in samba 3.2 and 3.6.
idmap backend = tdb
idmap uid = 10000-99999
idmap gid = 10000-99999
# no .tld
idmap config TEST:backend = rid
idmap config TEST:range = 10000-9999
winbind enum users = yes
winbind enum groups = yes
# This way users log in with username instead of<EMAIL_ADDRESS>winbind use default domain = yes
# Inherit groups in groups
winbind nested groups = yes
winbind refresh tickets = yes
winbind offline logon = true
# Becomes /home/example/username
template homedir = /home/%D/%U
# No shell access
template shell = /bin/false
client use spnego = yes
client ntlmv2 auth = yes
encrypt passwords = yes
restrict anonymous = 2
log file = /var/log/samba/samba.log
log level = 2
# This define a share with samba
[Shared-Name]
comment = My shared folder
path = /shared
valid users = "@TEST\Shared_Group"
force group = "shared_group"
writable = yes
read only = no
force create mode = 0660
create mask = 0777
directory mask = 0777
force directory mode = 0770
access based share enum = yes
hide unreadable = yes
Remember to enter users in the TEST\Shared_Group enabled to read and write in our share.
Configure services
We enable and start Samba:
# systemctl start smb nmb winbind
# systemctl enable smb nmb winbind
Let’s join our Linux server with the TEST.LOCAL domain and disable “Guests” groups to access on our share folder:
# net -s /dev/null groupmap add sid=S-1-5-32-546 unixgroup=nobody type=builtin
# net ads join -U administrator
Create the share
Finally we can create our share folder named shared and assign it the correct permissions at the share level.
# mkdir /shared
# chmod -R 0772 /shared
# chgrp -R "Domain Users" /shared
Now test the samba share with samba client.
$ smbclient //localhost/Shared-Name -U arthur%password
Configure NFS
For other Unix machine, is very useful NFS share. Because this, configure it:
# vim /etc/exports
/shared <IP_ADDRESS>/24(rw,sync) # Substitute with your ip address in CIDR notation
And enable services
# systemctl start rpcbind nfs-server
# systemctl enable rpcbind nfs-server
Conclusion
Now, all that remains is to connect from a Windows machine (or Linux, why not, with samba client) and write and read files. This is a good way to merge two apparently incompatible worlds when it comes to sharing files and folders.
Another advantage of having a file server on the Unix platform is that you can automate a lot of tasks through scripts created with bash, perl or python. Also, if you could map the same shared folder with samba also with the NFS protocol, a more practical way for Unix platforms.
In short, this is a good practice for sharing files between different platforms.


Recommended OVA VM settings:
-
8 CPUs, 16GB RAM or A3, A4 or A7 on Azure marketplace.
-
Three windows or Linux nodes, each with more than 15GB free space.
-
Alternatively, you can connect only cloud resource (Azure blob storage or AWS S3) and start working immediately.
Firewall
- The nodes need network access on port 8443 to the VM
- The nodes and the core VM need network access one to another on one of the ports 60100-60600 (configurable).
- NooBaa core (VM) management ports are 8080 and 8443
- High availability - open port 27000
- S3 public access ports are 80 and 443


I would not have guessed my journey into computer science would lead me to medical school.
Computer science fulfills my passion to create. As a medium, my inner engineer is given a platform to explore, understand and develop systems. I love using technology to build systems that enable others to do things that were once previously impossible for them.
However, learning the differences between healing and enabling has transformed computer science into my personal stepping stone to medicine. I entered the field of accessibility as an undergraduate. From there, it took me 8 years of exploring the role interfaces play in the lives of handicapped individuals, understanding how computers work, and building stuff to finally learn why I want to marry technology and medicine.
At the end of the day, the relationships I form with users are the most valuable aspect of my work, and that is an aspect I feel computer science fails to emphasize, unjustly so. Learning about people’s dreams and insecurities collectively shape the role I hope to play in their lives. That being said, I feel there is a disconnect when I serve people tangentially through technology. I am choosing to address that disconnect through the role I hope to play in medicine.
The process of learning about people’s dreams and insecurities collectively shape the role I hope to play through medicine. That role became clear to me in bits and pieces through shadowing physicians. Observing their relationships with patients allowed me to see how healing encompasses many things; among those are direct care, devotion, and service to patients. Despite the different procedures I witnessed, each specialty demonstrated an almost identical form of these elements. Valuing education and exemplifying strong desires to teach, each physician stopped multiple times a day to make sure the patients and I were learning. The sprint to reassure the family of a premature baby of a successful surgery felt one in the same as the compassion I felt watching the creation of a group clinic for underserved populations in rural NC.
As a programmer serving the disabled, I can cater to physical limitations – but I cannot heal. I believe computer science is a powerful tool, but medicine is the foundation I must have in order to fulfill my desire to directly serve and care for others. I do not want to just alleviate frustrations, but rather help others rehabilitate their lives. After pursuing a career of service based on my abilities as a programmer, I have learned firsthand that computer science alone is not enough to serve others the way I want. With medicine I hope to fill the void created by these limitations to provide more comprehensive and direct care by bridging the strengths of both disciplines.
That is what it took for me to realize I needed to make the shift into medicine. I found myself asking whether or not I’m happy with how I spent my time in graduate school. I knew the answer was no, but I had no idea where that dissatisfaction came from, and I believe it was because I was afraid of what I’d find out. Leaving one career path for another is horrifying at first. But driven by the right reasons, those fears just don’t exist. I encourage everyone to ask those really hard questions and identify their drives. The journey is incredibly hard but incredibly rewarding. You won’t have any regrets.
I know I’m so excited to have found my role in cancer genomics, and am looking forward to pursuing my life in medicine.


arpeggiation: The generation of sequences of notes based on a chord played by the user, which are then played by a single {_voice}. Several of the keyboard algorithms perform arpeggiation.
Note that keyboard algorithms are performed by the {_preprocessor}, so the resulting arpeggiated notes are what is sent to the MIDI record output, not the original chord.


Trumper.
Show my profile
Leave the US. (log out)
Switch to global news timeline
Switch to own news timeline
Found Users
Trumper.
(You aren't following this user.)
(This is your account.)
(You are following this user. Nice!)