tag:blogger.com,1999:blog-11091877778030587942024-02-20T22:35:16.237-07:00Amortize ThisChris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.comBlogger85125tag:blogger.com,1999:blog-1109187777803058794.post-2395086195052442472014-09-09T07:33:00.003-07:002014-09-09T07:33:54.594-07:00Mortgage Lenders, Do the Right Thing<br />
<span style="font-family: Calibri;">“<i style="mso-bidi-font-style: normal;">Integrity is doing
the right thing, even when no one is watching</i>.” – C.S. Lewis<o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The mortgage industry brought trouble upon itself when too
many people in the industry weren't doing the right thing, and no one was
watching.<span style="mso-spacerun: yes;"> </span>Now everyone is watching, the
CFPB, OCC, and each of the states’ regulators. <span style="mso-spacerun: yes;"> </span>The prefaced C.S. Lewis quote makes the distinction
that integrity is doing the right think simply because it is the right thing to
do, not because you will otherwise get into trouble.<span style="mso-spacerun: yes;"> </span>The mortgage lenders that are still around today
likely were well-intentioned during the housing bubble, and did the right thing
when the regulators weren't looking.<span style="mso-spacerun: yes;"> </span>But
now we are in a position to not only do the right thing, but document and prove
that we do the right thing.<span style="mso-spacerun: yes;"> </span>This adds
costs which are ultimately charged to consumers.</span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS6_zjiw52-s_JYV0W743E29insn2ze_8FE_60a9lS_EXz9GU_zUmrtFSQX48DLO-q9cMF90TNe1CMWOn0L6gFXrKsJrBnz47bPuvPckutVlvNlNAcugos4MnUJEowpNgxxCAgaj9wsy4/s1600/Soup-RESPA.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS6_zjiw52-s_JYV0W743E29insn2ze_8FE_60a9lS_EXz9GU_zUmrtFSQX48DLO-q9cMF90TNe1CMWOn0L6gFXrKsJrBnz47bPuvPckutVlvNlNAcugos4MnUJEowpNgxxCAgaj9wsy4/s1600/Soup-RESPA.jpg" height="320" width="210" /></a><span style="font-family: Calibri;">In our business, we <i style="mso-bidi-font-style: normal;">will</i>
be in trouble with our regulators and our customers if we don’t follow the
alphabet soup of laws and regulations that we face:<span style="mso-spacerun: yes;"> </span>RESPA, ECOA, TILA, HMDA, ATR, MDIA, UDAAP,
HOEPA, FCRA, etc.<span style="mso-spacerun: yes;"> </span>But when we apply C.S.
Lewis’ definition of integrity to our core values, then we follow these rules
because it is the right thing to do.</span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Each of us in the mortgage industry has the responsibility to understand the rules
and abide by them.<span style="mso-spacerun: yes;"> </span>Ignorance of the
rules is not a valid excuse to violate them.<span style="mso-spacerun: yes;">
</span>The CFPB has made that clear. <span style="mso-spacerun: yes;"> </span></span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Today we are taught to do the right thing because of the plethora
of ways for us to get into trouble, but ultimately if we do the right thing
because it is right for the consumer, I believe (translated "I hope") that we will
escape the wrath of regulators.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com8tag:blogger.com,1999:blog-1109187777803058794.post-70719009397788799462014-08-26T19:17:00.004-07:002014-08-26T19:17:45.488-07:00Mixed Messages From a Schizophrenic Economy<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Initial jobless claims fell to 302,000, better than
expected.<span style="mso-spacerun: yes;"> </span>That’s great news, right?<span style="mso-spacerun: yes;"> </span>The economy is bouncing back, right?<span style="mso-spacerun: yes;"> </span>Not so fast, my friend!<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIEgSB8r43X3j82XAM8FvtYiI72S2xLLSyRhsmcoxHHs4VEDCUx8nekIW5SNnC1BQ3g_BWaiWa46bqE0qDi4lNkXZvZVH3xkCYFhnMd1eMEjg4qOZjCwue_TAeb9N48gbRsUEEUCsP35o/s1600/schizophrenia-300x285.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIEgSB8r43X3j82XAM8FvtYiI72S2xLLSyRhsmcoxHHs4VEDCUx8nekIW5SNnC1BQ3g_BWaiWa46bqE0qDi4lNkXZvZVH3xkCYFhnMd1eMEjg4qOZjCwue_TAeb9N48gbRsUEEUCsP35o/s1600/schizophrenia-300x285.jpeg" height="190" width="200" /></a><span style="font-family: Calibri;">The initial jobless claims report is just another mixed message
from our schizophrenic economy that stumbles through a weak recovery.<span style="mso-spacerun: yes;"> </span>There are positive signs for unemployment,
inflation, and job creation.<span style="mso-spacerun: yes;"> </span>But GDP
growth, wage growth, labor force participation, and labor productivity all
remain weak.<span style="mso-spacerun: yes;"> </span>What’s a Fed Chairwoman to
do?<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">As QE winds down, Fed Chair Janet Yellen and the rest of the
Federal Reserve Board want to begin the inevitable process of raising short
term interest rates, but they won’t until the economy shows that it can stand
on its own two feet.<span style="mso-spacerun: yes;"> </span>The risk of relying
completely on past statistics and waiting too long is that inflation may sneak
up on us and get out of control.<span style="mso-spacerun: yes;"> </span>That
could give the economy an entirely new set of problems.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The Fed has a very difficult challenge ahead of it.<span style="mso-spacerun: yes;"> </span>When they decide to raise rates , it will
impact all of us.<span style="mso-spacerun: yes;"> </span>But with so many weak
indicators of the economy, it will be extremely difficult for them to raise
rates anytime soon.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1tag:blogger.com,1999:blog-1109187777803058794.post-47624384482275718132014-08-13T09:10:00.002-07:002014-08-13T09:10:36.943-07:00In Suburbia<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">“Let’s take a ride, and run with the dogs tonight, in
Suburbia.”<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">I have no clue what the Pet Shop Boys meant with that line
of their 1986 hit song, “Suburbia.”<span style="mso-spacerun: yes;"> </span>It
seems to me that one would either take a ride with the dogs, or run with the
dogs, but not both.<span style="mso-spacerun: yes;"> </span>But regardless if
you are riding or running, more people seem to be doing both in “Suburbia,” more
commonly called “the suburbs.”<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGE5Oihyt9V3ygm-GjHRAzt-B9hIED_yjYy2f_pW-jDtiDH44z24ouo5El3I4ICxTglkc7J09DFBqX7TdBrfqnIdn2g3Zl8Ao_Bu8lqQ_gbCbZdAeRPkdmcc4u5-yQBGXbG9ag05Jpwi4/s1600/brady+bunch+house.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGE5Oihyt9V3ygm-GjHRAzt-B9hIED_yjYy2f_pW-jDtiDH44z24ouo5El3I4ICxTglkc7J09DFBqX7TdBrfqnIdn2g3Zl8Ao_Bu8lqQ_gbCbZdAeRPkdmcc4u5-yQBGXbG9ag05Jpwi4/s1600/brady+bunch+house.png" /></a><span style="font-family: Calibri;">This reverses a prior trend that showed that America’s big
cities have grown faster than their suburbs in recent years.<span style="mso-spacerun: yes;"> </span>A report from the U.S. Census Bureau shows
that fourteen of the nation’s 20 biggest cities saw their growth slow or
populations decrease in 2013.<span style="mso-spacerun: yes;"> </span>Only 18 of
America’s 51 metropolitan areas with populations greater than 1 million people
had their cities grow faster than their suburbs.<span style="mso-spacerun: yes;"> </span>That’s down from 25 in 2012.<span style="mso-spacerun: yes;"> </span>So now it’s Suburbia that is growing faster
than the urban core of cities.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Why the change?<span style="mso-spacerun: yes;"> </span>Just
recently we were discussing the appeal of condominiums in the core of major
cities.<span style="mso-spacerun: yes;"> </span>While those projects are selling
well, it seems that greater growth is attributed to single family homes with
yards and fences.<span style="mso-spacerun: yes;"> </span>Most of us that grew
up in the west grew up in a suburb.<span style="mso-spacerun: yes;"> </span>That
trend continues, especially for families with children.<span style="mso-spacerun: yes;"> </span>That’s good news for home builders, and the
economy since the construction of single family homes creates more jobs than
multi-family projects.<o:p></o:p></span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.blogger.com/editor/static_files/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="" /></a></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-11159831545415188262014-08-12T08:13:00.000-07:002014-08-12T08:13:12.259-07:00Ducks in a Row<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">We’ve all used, or at least heard, the expression, “Get your
ducks in a row.”<span style="mso-spacerun: yes;"> </span>Generally it is in the
context of organizing so that we are prepared for a meeting or event.<span style="mso-spacerun: yes;"> </span>Why ducks?<span style="mso-spacerun: yes;">
</span>And why would ducks need to be in a row?<span style="mso-spacerun: yes;">
</span>More on that later.<o:p></o:p></span></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguQXwRH5m23UQ468BelEIDqojaEcxNseVjWG1-0KrN3DgMo1XbqFB462a0Ao5-RINarpg8ewbkXGOO8yZ-PVkolAZ5OdBYp2HjspmT8PKfgFNBTTquLs7LrBs9Z63ojRiOGaPslNI3Gxs/s1600/ducks+in+a+row.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguQXwRH5m23UQ468BelEIDqojaEcxNseVjWG1-0KrN3DgMo1XbqFB462a0Ao5-RINarpg8ewbkXGOO8yZ-PVkolAZ5OdBYp2HjspmT8PKfgFNBTTquLs7LrBs9Z63ojRiOGaPslNI3Gxs/s1600/ducks+in+a+row.png" /></a><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">When applying for a mortgage, getting one’s “ducks in a row”
makes the process move much more smoothly.<span style="mso-spacerun: yes;">
</span>One should be sure to keep well-organized personal files with income and
asset documentation, so that when the documentation is asked for by the lender,
it can be delivered quickly and without much headache.<span style="mso-spacerun: yes;"> </span>When completing a mortgage application, have
the following documents ready to provide to your lender:<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Paystubs covering most recent 30 day period<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">W-2 forms for the most recent 2 years<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Tax returns for the most recent 2 years<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Bank statements for the most recent 2 months<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Explanation for any derogatory credit<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Be ready for some additional documentation if
you own your own business<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Now that you know how to have your “ducks in a row” for a
mortgage loan, let’s get back to the ducks.<span style="mso-spacerun: yes;">
</span>I found quite a few explanations for the “ducks in a row” idiom.<span style="mso-spacerun: yes;"> </span>One of them is from a newspaper story in 1901
about a game hunter that supposedly killed 42 wild ducks by baiting them with
corn in a long galvanized trough and firing just once with a large shot
gun.<span style="mso-spacerun: yes;"> </span>The more likely and less gruesome
origin could be the common image of the mother duck leading a straight line of
ducklings waddling in a row, one behind the other.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-62437581202485164432014-07-27T17:54:00.000-07:002014-07-27T17:54:57.327-07:00How Much Can I...?<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">I sometimes get annoyed when I ask a question and the answer
I receive is another question, but I am often guilty of that response
myself.<span style="mso-spacerun: yes;"> </span>So when I am asked “How much can
I qualify for?” by someone that wants to be prequalified for a mortgage, I
often answer with a couple of questions.<span style="mso-spacerun: yes;">
</span>First, “How much do you pay now for housing?” and “How much are you
comfortable budgeting each month for housing?”<span style="mso-spacerun: yes;">
</span>From there I work to calculate debt to income ratios to see if the
homebuyers budgeting expectations are in line with underwriting guidelines.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">It is tempting, but dangerous to find a house and then
reverse engineer a budget that is dramatically different from one’s current
spending habits.<span style="mso-spacerun: yes;"> </span>Don’t get me wrong,
it’s great to trim unnecessary expenses out of the budget, but people need to
be realistic about what changes they are willing to make about their expenses
and how it affects their overall happiness.<span style="mso-spacerun: yes;">
</span>Instead of just telling the homebuyer the maximum amount they can borrow
and still get approved, we have a deeper discussion about what they can truly
afford.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Every new homebuyer should create a household budget,
especially when the home purchase results in an increase in their monthly
housing expenses.<span style="mso-spacerun: yes;"> </span>Consider all expenses
when creating the budget.<span style="mso-spacerun: yes;"> </span>There are a
number of expenses that a lender won’t consider when qualifying a buyer such as
tuition, medical insurance, prescriptions, as well as discretionary costs.<span style="mso-spacerun: yes;"> </span>These can be major expenses and will impact
how much is available to pay for a home.<span style="mso-spacerun: yes;">
</span>Depending on lifestyle, travel and hobby expenses can greatly impact a
household budget.<span style="mso-spacerun: yes;"> </span>Pricey hobbies like
golf and skiing, or even pets can take a bite out of a monthly budget.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">At least one of the line items on a budget should be
savings.<span style="mso-spacerun: yes;"> </span>This can be for retirement,
college, or any other financial goal.<span style="mso-spacerun: yes;">
</span>All of these costs are real and should be considered by a homebuyer when
deciding how much they are willing to pay for the roof over their head.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
</div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com2tag:blogger.com,1999:blog-1109187777803058794.post-53843621384785590262014-07-26T14:44:00.002-07:002014-08-10T07:32:15.653-07:00Bad News in Portugal is Good News on Main Street U.S.A.
<span style="font-family: Calibri;">Poor Portugal.<span style="mso-spacerun: yes;"> </span>First
their national soccer team and superstar Cristiano Ronaldo failed to advance
past the group stage of the World Cup.<span style="mso-spacerun: yes;">
</span>Now concerns over the solvency of the major Portuguese bank, Banco
Espirito Santo, is creating waves through the global financial system.<span style="mso-spacerun: yes;"> </span>Stock markets are moving downward on the
uneasiness.<span style="mso-spacerun: yes;"> </span>Coincidently, Cristiano
Ronaldo is also a paid spokesperson for Banco Espirito Santo (see BES
advertisement).<o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In this case, and in general, bad news for the stock market
and other securities drives investors to the safety of U.S. bonds.<span style="mso-spacerun: yes;"> </span>That leads to lower mortgage interest rates
for American homebuyers.<span style="mso-spacerun: yes;"> </span>So those of you
in the market to purchase a home or refinance are in a position to benefit from
the struggles of Portugal, Banco Espirito Santo, and Cristiano Ronaldo.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1tag:blogger.com,1999:blog-1109187777803058794.post-47342999898723014722014-07-26T14:11:00.001-07:002014-07-26T14:11:36.280-07:00Condos are Movin' on Up
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Condos are “Movin’ on
Up”<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">One of the more dynamic segments of the housing markets is
the condo market.<span style="mso-spacerun: yes;"> </span>As the overall real
estate market recovered from the recession, condos have come back strong.<span style="mso-spacerun: yes;"> </span>Many “broken” projects that were victims of
poor timing in 2007-2008 have new life and strong sales.<span style="mso-spacerun: yes;"> </span>Luxury condo projects in highly desirable
locations are in demand.<span style="mso-spacerun: yes;"> </span>Likewise, more
moderately priced condos allow budget conscious homebuyers entry into
neighborhoods where single family homes are priced out of reach.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVBywt2_aari_GhEE2RUmlYHUAoo-iAxcPlpzGtjfiAPf1SXiBqoiBLiU_NxCpMQGWJ53cXj53XEKR7ih3KKZuvvBxtRJ_yd5WAkzaSIAiUOO-Lq1XoH6Z7l0h8u-KagTVdCqHOqhbXK4/s1600/Movin+on+Up.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVBywt2_aari_GhEE2RUmlYHUAoo-iAxcPlpzGtjfiAPf1SXiBqoiBLiU_NxCpMQGWJ53cXj53XEKR7ih3KKZuvvBxtRJ_yd5WAkzaSIAiUOO-Lq1XoH6Z7l0h8u-KagTVdCqHOqhbXK4/s1600/Movin+on+Up.jpg" /></a><span style="font-family: Calibri;">In order for buyers to obtain conventional financing for
condo, the project must be approved by the lender.<span style="mso-spacerun: yes;"> </span>In general, here are just a few of the
guidelines that lenders must follow when offering mortgages on condos:<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">No more than 50% of the project’s units may be
occupied by renters<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">For new projects, as few as 50% of the units
must have been conveyed or under contract for purchase<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">No single entity may own more than 10% of the
units<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">No more than 15% of the total units can be more
than 30 days delinquent on association fee payments<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Minimum insurance coverage and other
requirements apply<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Condos may also be financed with FHA and VA home loans with
project approval.<span style="mso-spacerun: yes;"> </span>Condos are an
attractive form of housing for a growing number of people that desire low
maintenance living in an urban environment.<span style="mso-spacerun: yes;"> </span></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-62607594466989023322014-04-15T09:38:00.002-07:002014-04-15T09:38:41.533-07:00Lend Responsibly: Subprime Safety<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihUTJ8eiPROIf_j8FysKBHOQKXoUiLjotOe_lzXvUGOBFqxA-pjZ5VyjjbQefVcB2FB4A7TSCaXflOtnAvrk3tK-hpoMADzfZHdIsPhNmmFpYKUD2Jn-k71IKQs9VCK5rOipikYHMHVTQ/s1600/open-bar.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihUTJ8eiPROIf_j8FysKBHOQKXoUiLjotOe_lzXvUGOBFqxA-pjZ5VyjjbQefVcB2FB4A7TSCaXflOtnAvrk3tK-hpoMADzfZHdIsPhNmmFpYKUD2Jn-k71IKQs9VCK5rOipikYHMHVTQ/s1600/open-bar.gif" /></a><span style="font-family: Calibri;">Back in 2007, “subprime” became a dirty word.<span style="mso-spacerun: yes;"> </span>In the years leading up to the recession,
lenders became increasingly aggressive in their lending guidelines in the
pursuit of a greater market share of a very profitable business.<span style="mso-spacerun: yes;"> </span>Looking back it is obvious that subprime
lending had gotten out of control like an alcoholic at an open bar.<span style="mso-spacerun: yes;"> T</span>here was no chance that the evening
would end well.<o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">But should subprime be forever banned from the housing
finance market?<span style="mso-spacerun: yes;"> </span>Of course not.<span style="mso-spacerun: yes;"> </span>Even the alcoholic can be fun to have at a
party as long as we don’t let him drink anything stronger than ginger ale.<span style="mso-spacerun: yes;"> </span>There is a need for sober subprime lending in
the housing market.<span style="mso-spacerun: yes;"> </span>In fact, some
responsible subprime lending has already returned.<span style="mso-spacerun: yes;"> </span>Wisely, no one actually refers to it as
“subprime,” since to many people that is still a dirty word.<o:p></o:p></span></div>
<span style="font-family: Calibri;">There are mortgage products available today to homeowners with less than perfect credit, but they require strong income documentation and a sizable down payment.<span style="mso-spacerun: yes;"> </span>As more private capital
becomes confident in the mortgage market, we will see an expansion of
responsible subprime lending. But let's promise to keep it under control.</span>Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-12063144950061411552014-03-13T09:28:00.000-07:002014-03-15T15:50:53.992-07:00That's a lot of Boomerangs!<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In 2013, singer-songwriter Lyfe Jennings introduced his hit
song “Boomerang” (just ask your kids if you haven’t heard it!). The lyrics
include the line “So throw me away, cause if I were a boomerang, I’d turn
around and come back to you.”<span style="mso-spacerun: yes;"> </span>Likewise,
in 2014 the housing industry will have a big hit from “Boomerang Buyers.”<span style="mso-spacerun: yes;"> </span>If you’re not familiar with this term, you’ll
soon understand the analogy.<span style="mso-spacerun: yes;"> </span>From 2008
through 2013 there were 269,049 properties in the Greater Phoenix area that
were either foreclosed or short sold.<span style="mso-spacerun: yes;"> </span>Those
former homeowners that experienced defaults have for the most part been thrown
out of the homebuyer market.<span style="mso-spacerun: yes;"> </span>But now in
most cases, those former homeowners are eligible to purchase homes again.<span style="mso-spacerun: yes;"> </span>They’re coming back.<span style="mso-spacerun: yes;"> </span>Ergo, they are dubbed “Boomerang Buyers.”<span style="mso-spacerun: yes;"> </span>In 2013 the top two markets for “Boomerang
Buyers” were Riverside-San Bernadino and Los Angeles.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The waiting period to qualify for a home loan after an event
like a foreclosure or short sale varies depending on the type of mortgage.<span style="mso-spacerun: yes;"> </span>Short sale waiting periods for conventional
loans range from 2 to 4 years, 3 years for an FHA loan.<span style="mso-spacerun: yes;"> </span>Foreclosure waiting periods range from 3 to 7
years.<span style="mso-spacerun: yes;"> </span></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Based on the number of short sales and foreclosures that
have already taken place, Fletcher Wilcox at Grand Canyon Title Agency
estimates that 42,444 previous homeowners that either short sold or were
foreclosed on will have completed the three year FHA waiting period and will be
eligible to purchase a home with an FHA insured loan in 2014.<span style="mso-spacerun: yes;"> </span>That’s a lot of boomerangs, and potentially a
lot of homebuyers coming into a market that has slowed down in recent
months.<span style="mso-spacerun: yes;"> </span>As the market shows slight signs
of softening, now is a great time for boomerang buyers to come back.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com2tag:blogger.com,1999:blog-1109187777803058794.post-22170876466185269952014-03-06T10:34:00.001-07:002014-03-15T15:49:42.417-07:005 Financial Benefits to Homeownership<div style="text-align: left;">
</div>
<div class="MsoNormal" style="margin: 0in 0in 10pt; text-align: left;">
<span style="font-family: Calibri;">In our article from a few weeks ago, “Ownership Generation,”
we explored social and emotional reasons why young renters grow up to be
homeowners.<span style="mso-spacerun: yes;"> </span>But the reasons to buy a
home are not just warm and fuzzy.<span style="mso-spacerun: yes;"> </span>There
are also cold-hard money related advantages too.<span style="mso-spacerun: yes;"> </span>In this article we will discuss some financial
benefits to owning the roof over your head.<span style="mso-spacerun: yes;">
</span>This list of benefits is adopted from a December 2013 report from the
Joint Center for Housing Studies at Harvard University.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font-family: Calibri;">1.</span><span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";"> </span></span></span></b><b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Housing is the one leveraged investment
available<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">According to the report, “Homeownership allows households to
amplify any appreciation on the value of their homes by a leverage factor.”<span style="mso-spacerun: yes;"> </span>For example, if a home is purchased with a
10% down payment, and the home appreciates by 10%, the homeowner has doubled
their investment even though the value of the home increased by only 10%.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font-family: Calibri;">2.</span><span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";"> </span></span></span></b><b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">You’re paying for housing whether you own
or rent<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">When making a mortgage payment part of that payment goes to
pay down the principal which increases your equity.<span style="mso-spacerun: yes;"> </span>With rent, you’re only improving the
landlord’s equity position.<span style="mso-spacerun: yes;"> </span>I would also
add that rent is similar to an adjustable rate mortgage, as each year there is
the risk that the payment will increase.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font-family: Calibri;">3.</span><span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";"> </span></span></span></b><b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Owning is usually a form of “forced
savings”<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The report states that “Having to make a housing payment one
way or the other, owning a home can overcome people’s tendency to defer
savings.”<o:p></o:p></span></div>
<br />
<div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font-family: Calibri;">4.</span><span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";"> </span></span></span></b><b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">There are substantial tax benefits to
owning<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Our tax code is very favorable to homeowners.<span style="mso-spacerun: yes;"> </span>Mortgage interest and property taxes can be
deducted each year from a household’s taxable income.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font-family: Calibri;">5.</span><span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";"> </span></span></span></b><b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Owning is a hedge against inflation<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Although our economy hasn’t experienced significant
inflation in many years, there is always a risk of inflation in the
future.<span style="mso-spacerun: yes;"> </span>According to the report, home
values tend to rise at or above the rate of inflation which is a valuable hedge
against inflation risk.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The homeownership rate in America fell as a result of the
recession, but the benefits of owning a home still apply.<span style="mso-spacerun: yes;"> </span>Those advantages are social and emotional,
but as we have demonstrated they are also financial.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-22913738810493951262014-03-04T10:01:00.000-07:002014-03-15T15:50:17.652-07:00Business Owner Blues<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Last week’s article “Getting a Mortgage These Days:<span style="mso-spacerun: yes;"> </span>It’s Not That Bad,” generated a lot of
questions specific to the challenges of qualifying business owners.<span style="mso-spacerun: yes;"> </span>As more of the workforce moves away from 9 to
5, W-2 employment, more potential homebuyers have a complicated task of
documenting their income for the purpose of qualifying for a mortgage.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4oBuJnPV4KzTF_8VSvHklLMGlc82SgzinBERsoNdrEsm_mQhV2WgDbr7xqIn9YVF0lUcZiyO20gZTh0T8nAwQ5rBtqHmJgS1PjPy_jdKU5uKV_gSGcLBLtqUt7noX2X1jw6h21Cak4Qc/s1600/business+owner.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4oBuJnPV4KzTF_8VSvHklLMGlc82SgzinBERsoNdrEsm_mQhV2WgDbr7xqIn9YVF0lUcZiyO20gZTh0T8nAwQ5rBtqHmJgS1PjPy_jdKU5uKV_gSGcLBLtqUt7noX2X1jw6h21Cak4Qc/s1600/business+owner.jpg" /></a><span style="font-family: Calibri;">The stated income loans of the past made qualification much
easier for self-employed borrowers.<span style="mso-spacerun: yes;">
</span>Today, due to legislation and rules responding to the Great Recession,
all income needed to qualify for a mortgage must be documented.<span style="mso-spacerun: yes;"> </span>For business owners or individuals that work
on contract, that generally means 2 years of individual and business tax
returns must be provided to the lender for review.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Applicants that have just started a business will find it
difficult, if not impossible; to qualify as the business must have a 2 year
history of generating income.<span style="mso-spacerun: yes;"> </span>Also, since
most new businesses rarely report a profit in the first year, the tax returns
are unlikely to reflect adequate qualifying income.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">One of the advantages of owning a business is having the
ability to write-off expenses related to the business from taxable income.<span style="mso-spacerun: yes;"> </span>This is wonderful for reducing tax liability,
but it also reduces the maximum loan amount that the business owner can qualify
for.<span style="mso-spacerun: yes;"> </span>The exception to this rule is
depreciation expenses.<span style="mso-spacerun: yes;"> </span>Since
depreciation is only a “paper” expense, the lender is able to add the reported
depreciation back to the applicant’s net income.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Yes, business owners must provide more documentation in
order to qualify for a mortgage, but we are closing loans for these types of
clients every day.<span style="mso-spacerun: yes;"> </span>With planning and
sound advice from a licensed mortgage professional, self-employed mortgage
applicants can navigate through the rules to qualify for and obtain a home
loan.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com2tag:blogger.com,1999:blog-1109187777803058794.post-56273300655840290752014-02-24T08:32:00.001-07:002014-03-15T15:53:37.281-07:00Getting a Mortgage These Days: It's Not THAT Bad!<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">I read an article this week titled “From ‘No Doc’ to ‘Every
Doc’” on <i style="mso-bidi-font-style: normal;">Fox Business</i>.<span style="mso-spacerun: yes;"> </span>In the article the author complained that
lenders have become too strict and make the mortgage process too cumbersome for
borrowers.<span style="mso-spacerun: yes;"> </span>At the same time he
rightfully acknowledged that if given the choice between the two, “Every Doc”
is a healthier choice than “No Doc” for borrowers, lenders, and the overall
economy.<span style="mso-spacerun: yes;"> </span>If you have read articles or
heard stories about how difficult it is to get a loan these days, here are a
few tips to help ensure the process is a smooth one.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Have a Documentable
Source of Income<o:p></o:p></span></b></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">For most people this is easy.<span style="mso-spacerun: yes;"> </span>Employees of companies receive paystubs and
W-2’s and their documentation is fairly straight forward.<span style="mso-spacerun: yes;"> </span>When fluctuating sources of income come into
play like commission or overtime additional documentation will be
required.<span style="mso-spacerun: yes;"> </span>Those types of income can be
used for qualification provided they are consistent or improving year over
year, and are documented for at least 2 years.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Self-employed borrowers have had the toughest transition
since the days of “no doc” or stated income loans.<span style="mso-spacerun: yes;"> </span>Many business owners write-off so many
expenses on their tax returns that their remaining documented qualifying income
isn’t adequate for the loan amount they seek.<span style="mso-spacerun: yes;">
</span>Knowing that they need to provide their lender with two years of
personal and business tax returns, self-employed individuals should plan ahead
and thoroughly consider all expenses in the year or two proceeding when they
expect to apply for a mortgage.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Make Sure Down
Payment Funds are in a Documented Account<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Most buyers save up their down payment in an account in
their own name.<span style="mso-spacerun: yes;"> </span>Sometimes documenting a
down payment can get complicated if the funds are in a business account.<span style="mso-spacerun: yes;"> </span>This situation is not uncommon with
self-employed borrowers and can lead to additional documentation.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">If the down payment funds are in an account that doesn’t
belong to the borrower, then a gift needs to be documented between the owner of
the account and the borrower.<span style="mso-spacerun: yes;"> </span>Sometimes
the borrower sells an asset, like a car, that also must be documented so that
the down payment funds can be sourced.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">When reviewing bank statements to document the down payment,
the lender will question any large non-payroll deposit that is greater than 25%
of the borrower’s monthly gross income.<span style="mso-spacerun: yes;">
</span>Since most of the purchase price is covered by a loan, the lender is
trying to make sure that the borrower has their own assets (or a documented
gift) into the property.<span style="mso-spacerun: yes;"> </span>It’s their
“skin in the game.”<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Don’t Add Any New
Debt during the Process<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">While purchasing a home, please don’t purchase a car or any
other large item that will cause one to incur debt.<span style="mso-spacerun: yes;"> </span>Also, if one is purchasing new furniture or
appliances for the home, be sure not to buy it on credit without consulting
with your loan originator first.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">When thinking about buying a home, the first person one
should speak with is a licensed mortgage professional.<span style="mso-spacerun: yes;"> </span>Most real estate agents that value their time
won’t even show a buyer a home until they have been pre-qualified by a
lender.<span style="mso-spacerun: yes;"> </span>Consult with your lender first.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-58052444005194648652014-02-20T09:14:00.001-07:002014-03-15T15:51:38.498-07:00Ownership Generation<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">What was the impact of the housing bubble on the American
psyche?<span style="mso-spacerun: yes;"> </span>Is the American dream of
homeownership no longer held in high regard?<span style="mso-spacerun: yes;">
</span>Are millennials less likely to want to own a home when they saw their
parents lose their home to foreclosure?<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh720IBB1E4lD468EfmZTZZI_6FOOpBOrumZmxMUDaNnn4tbpc1ieKu0mvSrGP__Vzeghc9CdniRvresLeQDMJJeurqdrd3pg4C4aED9xE9JPU08xJKVgEGrqWkkd2L80Q5Z_vDjt14k1Y/s1600/dreaming.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh720IBB1E4lD468EfmZTZZI_6FOOpBOrumZmxMUDaNnn4tbpc1ieKu0mvSrGP__Vzeghc9CdniRvresLeQDMJJeurqdrd3pg4C4aED9xE9JPU08xJKVgEGrqWkkd2L80Q5Z_vDjt14k1Y/s1600/dreaming.jpg" /></a><span style="font-family: Calibri;">In the aftermath of the Great Recession, many experts
believe that young people will be more likely to grow up to be renters rather
than homeowners.<span style="mso-spacerun: yes;"> </span>There are advantages to
renting:<span style="mso-spacerun: yes;"> </span>mobility; low maintenance; and less
responsibility.<span style="mso-spacerun: yes;"> </span>All of those are aspects
are associated with the characteristics of young people which is why there
might be a belief that young people will grow up to be renters.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">So will more young people grow up to be renters?<span style="mso-spacerun: yes;"> </span>The key is that eventually young people do
“grow up,” and when they do their lives change.<span style="mso-spacerun: yes;">
</span>They get married, have children, and then they want some stability.<span style="mso-spacerun: yes;"> </span>Their kids enroll in school and suddenly they
are less mobile and take on more responsibility.<span style="mso-spacerun: yes;"> </span>The characteristics of the millennial
generation that experts say will result in more renters are really just
characteristics of young people.<span style="mso-spacerun: yes;"> </span>While
the stability that parents seek for their families is less secure if they don’t
own the home they live in.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The recession was a major setback for many people.<span style="mso-spacerun: yes;"> </span>It did in fact reduce the rate of
homeownership in America.<span style="mso-spacerun: yes;"> </span>But it is this
author’s belief that most Americans still want to own a home, and when they are
in a financial position to own a home they will do so.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com2tag:blogger.com,1999:blog-1109187777803058794.post-43067779740390454132014-01-21T14:24:00.000-07:002014-03-15T15:52:25.629-07:00Loans and Oranges<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">If you were to pick any industry and shrink it by 30%,
chances are that it would have a dramatically negative effect on the
participants in that industry. Let’s take citrus as an example.<span style="mso-spacerun: yes;"> </span>If the predictions in the country for citrus
consumption for the foreseeable future dropped by a third, you can probably
imagine what that would do to citrus farmers.<span style="mso-spacerun: yes;">
</span>Many of them would likely sell their farms and exit the business.<span style="mso-spacerun: yes;"> </span></span></div>
<span style="font-family: Calibri;"></span><br />
<span style="font-family: Calibri;"></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Calibri;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbGTxIQ0L3k11vZYuRzDqcKUhYeVscLvSc6g5q6dD91GIFwmGYNndDBAE7QAecF8dUq2pOnhA2gdVY8sw2Ju0RbqlZE_8Wo_uPPE9X4RmMZu1f8AahFje8GSprqWcZkDWYaQGxC26YeQ/s1600/oranges.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbGTxIQ0L3k11vZYuRzDqcKUhYeVscLvSc6g5q6dD91GIFwmGYNndDBAE7QAecF8dUq2pOnhA2gdVY8sw2Ju0RbqlZE_8Wo_uPPE9X4RmMZu1f8AahFje8GSprqWcZkDWYaQGxC26YeQ/s1600/oranges.jpg" height="213" width="320" /></a></span></div>
<span style="font-family: Calibri;">
<o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In addition, what would happen if the government started
telling the citrus farmers exactly what size, color and shape of oranges were
allowed to be sold in the open market? You would likely see a percentage of
these farmers getting out of the industry because their product no longer
conformed to government requirements.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The analogy about citrus farmers is not all that far off
from what the mortgage industry is experiencing right now.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The Mortgage Bankers Association recently dropped their 2014
forecast for loan originations.<span style="mso-spacerun: yes;"> </span>They
expect that the volume of loans originated this year will be a full one-third
less than what was originated in 2013.<span style="mso-spacerun: yes;">
</span>The main reason is that interest rates are rising and there is very
little refinance activity.<span style="mso-spacerun: yes;"> </span>Also, on
January 10<sup><span style="font-size: x-small;">th</span></sup> the <span style="mso-bidi-font-style: italic; mso-bidi-font-weight: bold;">CFPB's Qualified Mortgage Rule went into effect which eliminates
certain types of loans that mortgage bankers and brokers originated in the
past.<o:p></o:p></span></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">So what’s going to happen to those lenders that spent 2012
and 2013 riding the wave of easy refinance business?<span style="mso-spacerun: yes;"> </span>Who knows for sure, but many of them are
likely to go away. What will happen to lenders who did not prepare for the
recent regulatory changes in the industry? Some of them will be closing shop
too.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">This all sounds grim, but fear not! Even though many lending
companies will likely close shop or be forced out of the industry, there are
many others who have planned well and are prepared for the changes in our
industry. This is why it is important to align yourself with a lender that is intensely focused on helping homebuyers become homeowners.<span style="mso-spacerun: yes;"> </span>For example, our business model at Homeowners
Financial Group has been the same for over a decade.<span style="mso-spacerun: yes;"> </span>Sure,
we are happy to help our clients when they need a refinance, but we never lost
focus on our commitment to homebuyers and our partners in the home buying
process, real estate agents and builders.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In 2014 and beyond, make sure you work with a lender that has the know-how, commitment
and “staying-power” to succeed in today’s market.<span style="mso-spacerun: yes;"> </span></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1tag:blogger.com,1999:blog-1109187777803058794.post-2583997754354195782014-01-09T07:55:00.003-07:002014-01-09T07:57:40.710-07:00Keys for the Housing Market in 2014<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">2013 was characterized by a contrast between the first and
second half of the year.<span style="mso-spacerun: yes;"> </span>The first half
had the benefit of record low interest rates that helped to push up prices as
buyers attempted to out-bid each other for homes.<span style="mso-spacerun: yes;"> </span>Los Angeles saw an increase in median price
of nearly 30%, and Phoenix had an increase in excess of 50%.<span style="mso-spacerun: yes;"> </span>With higher prices in place, the second half
of the year also saw higher interest rates which tempered the strong
demand.<span style="mso-spacerun: yes;"> </span>So what should we expect in
2014?<o:p></o:p></span></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG6_dTXLvo4jxXnr8sns892KuWoFMxH0T6Qil7dXVrhcPMACwzAIK3vWTXqvUnseIpXOlV6PHNmGL2nCEMRp4W7Fi4iW4eXx_uBirqM69s7LqfQGVho3YA0LAS2YS3wFNnZC8GvmMgoq8/s1600/2014.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG6_dTXLvo4jxXnr8sns892KuWoFMxH0T6Qil7dXVrhcPMACwzAIK3vWTXqvUnseIpXOlV6PHNmGL2nCEMRp4W7Fi4iW4eXx_uBirqM69s7LqfQGVho3YA0LAS2YS3wFNnZC8GvmMgoq8/s1600/2014.jpg" height="160" width="200" /></a><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">There are reasons to believe that 2014 will be a strong year
for housing.<span style="mso-spacerun: yes;"> </span>But there are also some
concerns about where the market might go.<span style="mso-spacerun: yes;">
</span>As the old saying goes, “Hope for the best, but be prepared for the
worst.”<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Why 2014 will be a good year for housing.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Housing formations are expected to pick up which
will boost demand for new homes.<span style="mso-spacerun: yes;"> </span>This
will lead to an increase in construction as inventory levels have been
low.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">The overall economic picture should continue to
improve.<span style="mso-spacerun: yes;"> </span>Jobs are the driving force
behind housing, and as wages increase there will be more consumers in a position
to buy their first home or move-up.<span style="mso-spacerun: yes;">
</span>Also, delinquencies continue to fall which indicates consumers are in a
better financial position than they have been in recent years.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Although rates are rising, they are still very
low by historical standards which will aid affordability.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Now here’s the other side of the coin.<span style="mso-spacerun: yes;"> </span>What could derail the market in 2014?<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Speaking of interest rates…<span style="mso-spacerun: yes;"> </span>If rates continue to rise as expected it will
impact affordability and reduce demand.<span style="mso-spacerun: yes;">
</span>Most buyers still need a mortgage to purchase a home, and affordability
to them is mostly based on how much that monthly mortgage payment is.<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Some argue that the recovery we experienced in
the past year was a mirage.<span style="mso-spacerun: yes;"> </span>The Federal
Reserve’s stimulus (QE 1, 2, & 3) was the main driving force in making
payments so affordable (with low rates) that prices had to rise.<span style="mso-spacerun: yes;"> </span>Therefore when rates go up, those prices will
have to go back down.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In either perspective, inventories will play a critical role.<span style="mso-spacerun: yes;"> </span>There are far fewer foreclosures coming onto
the market which has contributed to the lack of inventory.<span style="mso-spacerun: yes;"> </span>Increases in new construction need to happen
to meet the demand, and as prices rise builders have greater incentive to build
homes.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The mortgage industry also plays a role.<span style="mso-spacerun: yes;"> </span>Credit is still perceived to be tight,
although the industry has made a lot of progress developing programs that don’t
fit in the conforming box, such as Homeowners Financial Group's Clean Slate product for buyers that have
a foreclosure or short sale on their record.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">If you’re looking for a prediction, you won’t find one
here.<span style="mso-spacerun: yes;"> </span>No one can say with certainty what
2014 will bring, but everyone should be aware of the key issues that will
determine what the year brings for housing.<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1tag:blogger.com,1999:blog-1109187777803058794.post-8294729471629004132013-12-23T10:57:00.000-07:002013-12-23T10:57:08.947-07:00Ho Ho Home! Gifting a Down Payment
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">On the first day of Christmas my true love gave to me …. a
down payment for a new home.<span style="mso-spacerun: yes;"> </span>As a lender
we commonly see transactions where the home buyer is receiving a gift from a
relative for the down payment.<span style="mso-spacerun: yes;"> </span>Since it
is the gifting season, we thought we should highlight some of the rules
associated with gifting a down payment.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglxvp9fgM3IVEPbGBTwVvhNuSIMwJpONI-HGYBL6xIHpBYgzVPMQTNzDVK1ZSvuWLmC_nSPI8ua5CYGVSFQfxmQlAZjMBHxL7QrK95dA5CECXXR5KPaujEhRRcspF3HNjekb1TWnREAC4/s1600/home+gift.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglxvp9fgM3IVEPbGBTwVvhNuSIMwJpONI-HGYBL6xIHpBYgzVPMQTNzDVK1ZSvuWLmC_nSPI8ua5CYGVSFQfxmQlAZjMBHxL7QrK95dA5CECXXR5KPaujEhRRcspF3HNjekb1TWnREAC4/s1600/home+gift.png" /></a><span style="font-family: Calibri;">For primary residences, conforming and FHA rules allow the
entire down payment to be in the form of a gift.<span style="mso-spacerun: yes;"> </span>The donor must be a relative which is defined
as a spouse, child or other dependent, or other individual who is related to
the borrower by blood, marriage, adoption, or legal guardianship; or a fiancée,
or domestic partner.<span style="mso-spacerun: yes;"> </span>Neither Fannie Mae
nor FHA mentions anything about a donor with a white beard, “broad face, and a
little round belly, that shook when he laughed like a bowl full of jelly.”<span style="mso-spacerun: yes;"> </span>The donor may not be affiliated with any
other party to the transaction such as a builder, developer, or real estate
agent.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Just as the home buyers’ own funds must be documented, gift
funds also require documentation.<span style="mso-spacerun: yes;"> </span>A
letter signed by the donor, called a gift letter, must include the following
information:<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Dollar amount of the gift,<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Date funds were transferred,<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Statement that no repayment is expected; and<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l1 level1 lfo1; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">The donor’s name, address, phone number, and
relationship to the home buyer.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The lender must also verify that sufficient funds to cover
the gift are available in the donor’s account, or have been transferred to the
home buyer.<span style="mso-spacerun: yes;"> </span>Acceptable documentation for
conforming loans includes:<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Copy of the donor’s check and home buyer’s
deposit slip,<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Copy of the donor’s withdrawal slip and the home
buyer’s deposit slip,<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Copy of the donor’s check or wire to the closing
agent, or<o:p></o:p></span></div>
<br />
<div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo2; text-indent: -0.25in;">
<span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal "Times New Roman";">
</span></span></span><span style="font-family: Calibri;">Copy of settlement statement showing receipt of
the donor’s funds.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">FHA has slightly different documentation requirements.<span style="mso-spacerun: yes;"> </span>Either way, no gift wrapping is required.<span style="mso-spacerun: yes;"> </span>Happy Holidays!<o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-39805033928016673332013-12-11T11:40:00.000-07:002013-12-11T11:40:47.023-07:00How Much Can Low Rates Save You on a Home?
This is an update of an earlier article posted on October 5, 2010.<br />
<br />
How much does a lower interest rate on a mortgage reduce the cost of a
home?<span style="mso-spacerun: yes;"> </span>That sounds like a simple
question. Of course a lower rate means a lower monthly payment. But how much of
a difference does that really make? <span style="mso-spacerun: yes;"> </span>I’ve
heard people over-simplify the issue by saying that a 1% change in rate is
roughly the same as a 10% change in price. Let’s look into this a little closer
and see if it holds up.<o:p></o:p><br />
<br />
We’ve all heard that interest rates today are at all-time lows. I think we
take that for granted, so it helps to include this chart that goes back to 1971.
It shows a 41-year trend of 30 year fixed mortgage rates. <span style="mso-spacerun: yes;"> </span>As you can see by the graph, mortgage rates
are near the lowest point that we have seen in our lifetimes.<o:p></o:p><br />
<br />
According to Freddie Mac, average conforming 30 year fixed mortgage rates
are around 4.5% .* If you were to purchase a home with a $350,000 home loan,
the monthly principal and interest payment at that rate would be $1,773.<o:p></o:p><br />
<br />
Now let’s see how raising the rate to the 2000 average of 8.05% affects the
payment. That’s not all that long ago. The payment at same loan amount at the
2000 rate is $2,580. We increased the rate by 3.55% and that resulted in a 45%
increase in payment! That seems worse than the 1% rate to 10% price ratio, but
let’s look at it from a price perspective.<o:p></o:p><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjLz3YLByMUhb_w3DATIY2P-pPEq8d0Sk15GhPtadbFLFqZVv8h2GOLMFSACb289FivtZVoyh1P2fZYaz34HquE5hF8vcGeZJLvfxIRg0rILtLwEhjIk3Tq1mXIz4PBeWFHqaC7W45jdA/s1600/Mortgage+Rates+Historical_Freddie+Mac.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjLz3YLByMUhb_w3DATIY2P-pPEq8d0Sk15GhPtadbFLFqZVv8h2GOLMFSACb289FivtZVoyh1P2fZYaz34HquE5hF8vcGeZJLvfxIRg0rILtLwEhjIk3Tq1mXIz4PBeWFHqaC7W45jdA/s400/Mortgage+Rates+Historical_Freddie+Mac.jpg" width="400" /></a>That increase in payment from $1,773 to $2,580 is the same as raising the
loan amount from $350,000 to $509,268. That is also a 45% increase in loan
amount. If the down payment is the same percentage for each example, then it
also results in a 45% increase in sales price.<o:p></o:p><br />
<br />
So for this example we discovered that a 3.55% increase in rate equals a 45%
increase in price. It also means a 1% increase in rate is equivalent to a 13%
increase in sales price.<o:p></o:p><br />
<br />
Don’t think I chose a year with an exceptionally high rate. I could have
used 1981 where rates were 16.63%. In fact, the average rate over the 36 years
is 9%. I chose 2000 because it wasn’t that far back in history. The lesson here
is that even though rates have risen over the past several months, we must
recognize what an amazing opportunity we have to borrow money at this specific
point in history. Years from now we can look at an updated version of this
graph realize what a great deal there was in 2013.<o:p></o:p><br />
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-57471296276747134072013-11-20T14:58:00.000-07:002013-11-20T15:03:15.664-07:00CFPB Publishes Final Rule on New Mortgage DisclosuresToday the Consumer Financial Protection Bureau issued their Final Rule on integrating disclosures that are currently required by Regulation X (RESPA) and Regulation Z (TILA). It was back on May 23, 2011 that I wrote an article about the CFPB's effort to remake the mortgage disclosures. Their name for the campaign was "Know Before You Owe," and it was the first time in my career that I had seen a regulator reach out to the public and industry in such an expansive manor to obtain feedback.<br />
<br />
The results of that campaign are in the rule which is available on the <a href="http://www.consumerfinance.gov/newsroom/consumer-financial-protection-bureau-adopts-rule-to-protect-consumers-sending-money-internationally/" target="_blank">CFPB website</a>. There are some very readable summaries for those of us whose brain begins to ache when reading legal documents. The CFPB's materials and communication on this issue are commendable. <br />
<br />
There are two new documents which will replace four existing documents. First is the Loan Disclosure. The Loan Disclosure will replace the Good Faith Estimate and the initial Truth in Lending Disclosure. Like the current upfront disclosures, this document must be provided to an applicant within three business days of the loan application.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwuLl_dUUC4k0w-kBeVVTxyDWi5MTbFiryUbsXFlc0voz57bRWHKwugzDLdp9hP2usAiyhGau0sGRAgYFCeXbZ-P7lYOoL7Z34QrTI9ScfeiS1PZJ4EgBpgkjWy_rD4AevHXVSed16Ftc/s1600/CFPB_2tone_Horiz_RGB.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwuLl_dUUC4k0w-kBeVVTxyDWi5MTbFiryUbsXFlc0voz57bRWHKwugzDLdp9hP2usAiyhGau0sGRAgYFCeXbZ-P7lYOoL7Z34QrTI9ScfeiS1PZJ4EgBpgkjWy_rD4AevHXVSed16Ftc/s320/CFPB_2tone_Horiz_RGB.png" width="320" /></a></div>
<br />
The other new document is the Closing Disclosure. This document replaces the HUD-1 Settlement Statement and the Final Truth in Lending disclosure. The Closing Disclosure must be provided to the applicant no less than three days prior to the loan closing. There are some additional restrictions about what fees can change prior to closing. None of the lender's fees, or fees for servicers that the borrower may not shop for can change. Any increase in APR greater than .125% requires an new Closing Disclosure and another three day waiting period. <br />
<br />
Lenders will need have have a strong process for accurately disclosing in order to make sure that disclosure issues don't arise and cause delays for closing. They will have plenty of time to prepare as the new rule doesn't go into effect until August 1, 2015. <br />
<script charset="ANSI" defer="" type="text/javascript">if ( typeof Evernote == 'undefined' ) {
/**
* Represents global evernote context (namespace).
* All objects should be a part of this namespace.
* @type {Object}
*/
Evernote = {};
}
Evernote.inherit = function( childConstructor, parentClassOrObject, includeConstructorDefs ) {
if ( parentClassOrObject.constructor == Function ) {
// Normal Inheritance
childConstructor.prototype = new parentClassOrObject;
childConstructor.prototype.constructor = childConstructor;
childConstructor.prototype.parent = parentClassOrObject.prototype;
childConstructor.constructor.parent = parentClassOrObject;
}
else {
// Pure Virtual Inheritance
childConstructor.prototype = parentClassOrObject;
childConstructor.prototype.constructor = childConstructor;
childConstructor.prototype.parent = parentClassOrObject;
childConstructor.constructor.parent = parentClassOrObject;
}
if ( includeConstructorDefs ) {
for ( var i in parentClassOrObject.prototype.constructor ) {
if ( i != "parent" && i != "prototype" && parentClassOrObject.constructor[i] != parentClassOrObject.prototype.constructor[ i ]
&& typeof childConstructor.prototype.constructor[ i ] == 'undefined' ) {
childConstructor.prototype.constructor[ i ] = parentClassOrObject.prototype.constructor[ i ];
}
}
}
if ( typeof childConstructor.handleInheritance == 'function' ) {
childConstructor.handleInheritance.apply( childConstructor, arguments );
}
if ( typeof childConstructor.prototype.handleInheritance == 'function' ) {
childConstructor.prototype.handleInheritance.apply( childConstructor, arguments );
}
return childConstructor;
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.EnClipper = {
enClipperProcessId: -1,
init: function() {
Evernote.ResponseReceiver.subscribe(this);
Evernote.Addin.getProcessID(document);
Evernote.Addin.allowSetForegroundWindow(this.enClipperProcessId);
},
onDataReceived: function(data) {
if(data && (data.type == "process_id")) {
Evernote.EnClipper.enClipperProcessId = data.data | 0;
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Proxy object for Evernote ActiveX component
* @type {Object}
*/
Evernote.Addin = {
_addon : null,
isAuthenticated: true,
init : function(addin) {
this._addon = addin;
},
/**
* Injects css specified by filename to specified document.
* @param fileName - path to css
* @param doc - document object
*/
injectStyleSheet : function(doc, fileName) {
try {
this._addon.InjectStyleSheet(doc, fileName)
} catch (e) {
Evernote.Logger.error( "Addin.InjectStyleSheet() failed " + e );
}
},
/**
* Injects script content to specified document
* @param doc - document object
* @param content - content of the script file
*/
injectScript : function(doc, content) {
try {
this._addon.InjectScript( doc, content );
}
catch ( e ) {
Evernote.Logger.error( "Addin.injectScript() failed " + e );
}
},
/**
* Loads file content from disk
* @param url - path to the file
*/
loadFile : function(url) {
try {
return this._addon.LoadFile( url );
} catch (e) {
Evernote.Logger.error( "Addin.loadFile() failed " + e );
}
},
/**
* Append message to log file with specified level.
* Supported levels:
* 0 - debug
* 1 - info
* 2 - warning
* 3 - error
* 4 - critical
* @param logLevel
* @param message
*/
log : function(logLevel, message)
{
try {
this._addon.Log(logLevel, message)
} catch (e) {
Evernote.Logger.error("Failed to log message '" + message + "' to the log file due to error: " + e);
}
},
/**
* Opens new note window.
*/
openNewNote : function() {
try {
this._addon.CreateNewNote();
} catch (e) {
Evernote.Logger.error("Failed to open new note window due to error: " + e);
}
},
/**
* Return path to directory on local filesystem for specified type.
* @param type - type of directory to return. Currently supported types:
* options - directory, where options configuration is stored.
* resources - directory, where resources are located (images, scripts, etc.)
*/
getPath : function(type)
{
try {
return this._addon.GetAddinPath(type);
} catch (e) {
Evernote.Logger.error("Failed to clip full page due to error " + e);
}
},
/**
* Returns localized message by code.
* @param code - number of message in resource file.
*/
getLocalizedMessage : function(code) {
try {
return this._addon.GetLocalizedString(code);
} catch (e) {
Evernote.Logger.error("Failed to retrieve localized message due to error " + e);
}
},
clipNote : function(content, options, sourceUrl, imageUrls, silent, doc ) {
var isSilentClip = silent ? 1 : 0;
var images = imageUrls;
if(!(images instanceof Array)) {
images = [imageUrls];
}
try {
var notebookUid = options.notebookUid | 0;
try {
notebookUid = options.notebookUid() | 0;
} catch(e) {
//Notebook uid is not a function, but just an integer that we saved on previous step, ignore exception here
}
this.ensureAuthenticated();
Evernote.Logger.debug("Clip to " + (notebookUid) + " with tags: " + options.tags.join(",") + " ; comment: " + options.comments);
return this._addon.ClipNote(options.title, content, sourceUrl, isSilentClip, images.join("#") , notebookUid, options.tags.join(","), "", doc,"EvernoteGlobalReceiver");
} catch (e) {
Evernote.Logger.error("Failed to clipNote due to error " + e);
}
},
getCursorXPosition : function() {
try {
return this._addon.GetCursorXPosition();
} catch (e) {
Evernote.Logger.error("Failed to retrieve localized message due to error " + e);
throw e;
}
},
/**
* Call Addin to get all notebooks (global "EvernoteGlobalReceiver" function is called with response)
* @param document - document object
*/
getNotebooks : function(document) {
this.ensureAuthenticated();
this._addon.GetNotebooks(document, "EvernoteGlobalReceiver", Evernote.NotebookTypes.PERSONAL);
this.ensureAuthenticated();
this._addon.GetNotebooks(document, "EvernoteGlobalReceiver", Evernote.NotebookTypes.BUSINESS);
this.ensureAuthenticated();
this._addon.GetNotebooks(document, "EvernoteGlobalReceiver", Evernote.NotebookTypes.LINKED);
},
/**
* Call Addin to get all personal tags (global "EvernoteGlobalReceiver" function is called with response)
* @param document - document object
*/
getTags : function(document) {
this.ensureAuthenticated();
this._addon.GetTags(document, "EvernoteGlobalReceiver");
},
/**
* Call Addin to get linked notebook tags (global "EvernoteGlobalReceiver" function is called with response)
* @param document - document object
*/
getLinkedTags : function(document, notebookUid) {
this.ensureAuthenticated();
this._addon.GetLinkedNotebooksTags(document, "EvernoteGlobalReceiver", notebookUid);
},
/**
* Returns document location address
* @param document - DOM document
* @return {*}
*/
getDocumentHref: function(document) {
return this._addon.GetDocumentHref(document);
},
allowSetForegroundWindow: function(id) {
this._addon.AllowSetForegroundWindow(id);
},
getProcessID: function(doc) {
this.ensureAuthenticated();
this._addon.GetProcessID(doc, "EvernoteGlobalReceiver");
},
resetAuthenticatedState: function() {
this.isAuthenticated = true;
},
//This function should be called before every call to Addin that will establish connection with EvernoteClipper process.
ensureAuthenticated: function() {
if(!this.isAuthenticated) {
throw new Evernote.AuthenticatedException("User is not authorized");
}
},
processError: function(error) {
if(error.code == Evernote.ErrorCodes.AUTHENTICATION_ERROR) {
this.isAuthenticated = false;
}
return false;
},
getEvernoteVersion: function(document) {
this._addon.GetEvernoteVersion(document, "EvernoteGlobalReceiver");
},
getServerLocation: function() {
try {
return this._addon.GetServerLocation();
} catch (e) {
Evernote.Logger.error("Failed to get Evernote server location due to error: " + e);
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.FileLogger = {
_addin : Evernote.Addin,
_log : function(level, message) {
if(level >= this.level)
this._addin.log(level, "JS: " + message);
},
debug : function(message) {
try {
this._log(0, message);
} catch(e) {
if(this._next) {
this._next.debug(message);
}
}
},
info : function(message) {
try {
this._log(1, message);
} catch(e) {
if(this._next) {
this._next.info(message);
}
}
},
warn : function(message) {
try {
this._log(2, message);
} catch(e) {
if(this._next) {
this._next.warn(message);
}
}
},
error : function(message) {
try {
this._log(3, message);
} catch(e) {
if(this._next) {
this._next.error(message);
}
}
},
setNext : function(logger) {
this._next = logger;
this._next.setLevel(this.level);
},
setLevel : function(level) {
this.level = level;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ConsoleLogger = {
debug : function(message) {
if(this.level >= Evernote.LoggerConfigurator.DEBUG) {
try {
console.info(message);
} catch(e) {
if(this._next) {
this._next.debug(message);
}
}
}
},
info : function(message) {
if(this.level >= Evernote.LoggerConfigurator.INFO) {
try {
console.info(message);
} catch(e) {
if(this._next) {
this._next.info(message);
}
}
}
},
warn : function(message) {
if(this.level >= Evernote.LoggerConfigurator.WARN) {
try {
console.warn(message);
} catch(e) {
if(this._next) {
this._next.warn(message);
}
}
}
},
error : function(message) {
if(this.level >= Evernote.LoggerConfigurator.ERROR) {
try {
console.error(message);
} catch(e) {
if(this._next) {
this._next.error(message);
}
}
}
},
setNext : function(logger) {
this._next = logger;
},
setLevel : function(level) {
this.level = level;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.AlertLogger = {
debug : function(message) {
alert("Debug: " + message);
},
info : function(message) {
alert("Info: " + message);
},
warn : function(message) {
alert("Warn: " + message);
},
error : function(message) {
alert("Error: " + message);
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.LoggerConfigurator = {
DEBUG : 0,
INFO : 1,
WARN: 2,
ERROR: 3,
getLogger : function() {
var logger = Evernote.FileLogger;
if(logger) {
logger.setLevel(this.WARN);
Evernote.ConsoleLogger.setNext(Evernote.AlertLogger);
logger.setNext(Evernote.ConsoleLogger);
return logger;
}
return Evernote.ConsoleLogger;
}
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Represents page context (have permissions to access and modify DOM objects)
*/
try {
PageContext = {
url: (location && location.href) ? location.href : document.location.href,
title: document.title,
META: "evernote-webclipper-extension",
getFavIconUrl : function() {
var links = document.getElementsByTagName("link");
var i;
for (i = 0; i < links.length; i++) {
if (links[i].rel) {
var rels = links[i].rel.toLowerCase().split(/\s+/);
if (Evernote.ArrayExtension.indexOf(rels, "icon") !== -1) {
// Found it!
return links[i].href;
}
}
}
//Try to get it from google web site
var re = new RegExp( "^[^:]+:\/+([^\/" + ":" + "]+).*$" );
var domain = PageContext.url.replace( re, "$1" );
return "http://www.google.com/s2/favicons?domain=" + domain.toLowerCase();
},
injectAdditionalTags : function() {
var url = document.location.href;
if ( url.match( /^https?:\/\/[a-z0-9-+\.]*(evernote|yinxiang)\.com\//i ) ) {
try {
var metas = document.getElementsByTagName( "meta" );
for ( var i = 0; i < metas.length; ++i ) {
if ( metas[i].name == PageContext.META ) {
return;
}
}
var meta = document.createElement( "meta" );
meta.name = PageContext.META;
meta.content = "installed";
var head = document.head;
if ( head ) {
head.appendChild( meta );
}
if ( document.body ) {
document.body.className += ((document.body.className) ? " " : "") + PageContext.META;
}
}
catch ( e ) {
alert( "PageContext.injectAdditionalTags() failed: " + e );
throw e;
}
}
}
};
if((document.readyState == "complete" || document.readyState == "interactive") && !window.PageContext) {
PageContext.injectAdditionalTags();
}
} catch(e) {
//Just ignore exception here
}</script><script charset="ANSI" defer="" type="text/javascript">/**
* String constants used in the project.
* @type {Object}
*/
Constants = {
CLIP_DIALOG_ID : "evernote-content",
OPTIONS_DIALOG_ID : "evernote-options-content"
};</script><script charset="ANSI" defer="" type="text/javascript">/*! jQuery v1.7.2 jquery.com | jquery.org/license */
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table>
<a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'>
<div style='"+t+"0;display:block;overflow:hidden;'>
</div>
</div>
"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"
<tr><td></td></tr>
</table>
",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table>
<tr><td style='"+t+"0;display:none'></td><td>t</td></tr>
</table>
",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'>
</div>
",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'>
</p>
";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'>
</div>
<div class='test'>
</div>
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>
","</fieldset>
"],thead:[1,"<table>","</table>
"],tr:[2,"<table><tbody>","</tbody></table>
"],td:[3,"<table><tbody>
<tr>","</tr>
</tbody></table>
"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>
"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>
","</div>
"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>
").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);</script><script charset="ANSI" defer="" type="text/javascript">/*!
* ClearlyComponent
* Offer up Clearly's content detection algorithm as an embeddable component.
*
* http://evernote.com/clearly/
* Copyright 2012, Evernote Corporation
*
* Requires:
* window.jQueryForClearlyComponent -- an instance of jQuery
*
* Definition:
* window.ClearlyComponent
* getContentElementAndHTML(_windowObject, _callbackFunction) {
* _callbackFunction({
* '_elements': [ (nodeObjects) ],
* '_html': (string),
* '_title': (string),
* '_multiPage': (bool),
* '_rtl': (bool)
* });
* }
* getOtherPagesHTML(_callbackFunction) {
* _callbackFunction(
* [
* {
* '_html': (string),
* '_url': (string)
* }
* ]
* );
* }
*/
function initClearly( window ) { /* override window object and undefined */
// set main objects
// ================
var $C = { 'version': '3335.890.162' };
var $ = window.jQueryForClearlyComponent;
var $R = { 'component': true };
// getContentElementAndHTML
// ========================
$C.getContentElementAndHTML = function (_windowObject, _callbackFunction)
{
// we're basically duplicating $R.getContent__find
// ===============================================
// get content
// ===========
var
_found = $R.getContent__findInPage($R.win),
_targetNode = _found._targetCandidate.__node,
_$targetNode = $(_targetNode),
_aboveNodes = []
;
// RTL
// ===
switch (true)
{
case (_$targetNode.attr('dir') == 'rtl'):
case (_$targetNode.css('direction') == 'rtl'):
$R.makeRTL();
break;
}
// get html
// ========
var
_foundHTML = _found._html,
_firstFragmentBefore = $R.getContent__nextPage__getFirstFragment(_foundHTML),
_documentTitle = ($R.document.title > '' ? $R.document.title : '')
;
// get title
// =========
// has title already?
_foundHTML = $R.getContent__find__isolateTitleInHTML(_foundHTML, _documentTitle);
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'target');
// get html above?
if ($R.articleTitle > ''); else
{
// get html above target?
// ======================
// global vars:
// _found
// _foundHTML
// _documentTitle
// _aboveNodes
var
_prevNode = _found._targetCandidate.__node,
_prevHTML = '',
_aboveHTML = '',
_differentTargets = (_found._firstCandidate.__node != _found._targetCandidate.__node)
;
(function ()
{
while (true)
{
// the end?
switch (true)
{
case (_prevNode.tagName && (_prevNode.tagName.toLowerCase() == 'body')):
case (_differentTargets && (_prevNode == _found._firstCandidate.__node)):
// enough is enough
return;
}
// up or sideways?
if (_prevNode.previousSibling); else
{
_prevNode = _prevNode.parentNode;
continue;
}
// previous
_prevNode = _prevNode.previousSibling;
// outline -- element might be re-outlined, when buildHTML is invoked
if ($R.debug) { $R.debugOutline(_prevNode, 'target', 'add-above'); }
// get html; add
_prevHTML = $R.getContent__buildHTMLForNode(_prevNode, 'above-the-target');
_aboveHTML = _prevHTML + _aboveHTML;
_aboveNodes.unshift(_prevNode);
// isolate title
_aboveHTML = $R.getContent__find__isolateTitleInHTML(_aboveHTML, _documentTitle);
// finished?
switch (true)
{
case ($R.measureText__getTextLength(_aboveHTML.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ')) > (65 * 3 * 3)):
case ($R.getContent__find__hasIsolatedTitleInHTML(_aboveHTML)):
return;
}
}
})();
// is what we found any good?
// ==========================
switch (true)
{
case ($R.getContent__find__hasIsolatedTitleInHTML(_aboveHTML)):
case (_differentTargets && (_aboveHTML.split('<a ').length < 3) && ($R.measureText__getTextLength(_aboveHTML.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ')) < (65 * 3))):
_foundHTML = _aboveHTML + _foundHTML;
break;
default:
_aboveHTML = '';
_aboveNodes = [];
break;
}
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'above_HTML');
// get document title?
if ($R.articleTitle > ''); else
{
// if all else failed, get document title
// ======================================
// global vars:
// _foundHTML
// _documentTitle
(function ()
{
// return?
// =======
if (_documentTitle > ''); else { return; }
// vars
var
_doc_title_parts = [],
_doc_title_pregs =
[
/( [-][-] |( [-] )|( [>][>] )|( [<][<] )|( [|] )|( [\/] ))/i,
/(([:] ))/i
]
;
// loop through pregs
// ==================
for (var i=0, _i=_doc_title_pregs.length; i<_i; i++)
{
// split
_doc_title_parts = _documentTitle.split(_doc_title_pregs[i]);
// break if we managed a split
if (_doc_title_parts.length > 1) { break; }
}
// sort title parts -- longer goes higher up -- i.e. towards 0
// ================
_doc_title_parts.sort(function (a, b)
{
switch (true)
{
case (a.length > b.length): return -1;
case (a.length < b.length): return 1;
default: return 0;
}
});
// set title -- first part, if more than one word; otherwise, whole
// =========
_foundHTML = ''
+ $R.articleTitleMarker__start
+ (_doc_title_parts[0].split(/\s+/i).length > 1 ? _doc_title_parts[0] : _documentTitle)
+ $R.articleTitleMarker__end
+ _foundHTML
;
})();
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'document_title');
}
}
// remember
// ========
$R.debugRemember['theTarget'] = _found._targetCandidate.__node;
$R.debugRemember['firstCandidate'] = _found._firstCandidate.__node;
// next
// ====
$C._nextPages = [];
$R.nextPage__firstFragment__firstPage = _firstFragmentBefore;
$R.nextPage__firstFragment__lastPage = $R.getContent__nextPage__getFirstFragment(_foundHTML);;
$R.nextPage__loadedPages = [$R.win.location.href];
$R.getContent__nextPage__find($R.win, _found._links);
// result
var
_result = {
'_html': _foundHTML,
'_title': $R.articleTitle,
'_multiPage': ($R.nextPage__loadedPages.length > 1),
'_rtl': $R.rtl
}
;
// add elements
_result['_elements'] = _aboveNodes;
_result['_elements'].push(_found._targetCandidate.__node);
// return
_callbackFunction(_result);
};
// getOtherPagesHTML
// =================
$C.getOtherPagesHTML = function (_callbackFunction)
{
// curent length
var
_currentLength = $C._nextPages.length
_checkFunction = function ()
{
if ($C._nextPages.length == _currentLength)
{
// return
_callbackFunction($C._nextPages);
}
else
{
// reset
_currentLength = $C._nextPages.length;
window.setTimeout(_checkFunction, 2000);
}
}
;
// set first timeout
window.setTimeout(_checkFunction, 2000);
};
// includes -- bind to $R
// ========
// target
// ======
// globals
// =======
$R.win = window;
$R.document = window.document;
$R.$win = $($R.win);
$R.$document = $($R.document);
// init
// ====
// version
// =======
$R.version = '3335.890.162';
// paths
// =====
$R.paths =
{
'main': 'none',
'evernote': 'https://www.evernote.com/'
};
// versioning
// ==========
$R.versioning =
{
'file_name_bulk_js': 'bulk.js',
'file_name_bulk_css': 'bulk.css',
'file_name_jQuery_js': 'jQuery.js',
'file_name_miniColors_js': 'jquery.miniColors.js',
'file_name_miniColors_css': 'jquery.miniColors.css',
'file_name_flexSelect_js': 'jquery.flexSelect.js',
'file_name_liquidMetal_js': 'liquidMetal.js',
'file_name_flexSelect_css': 'flexSelect.css',
'file_name_base--theme-1_css': 'base--theme-1.css',
'file_name_base--theme-2_css': 'base--theme-2.css',
'file_name_base--theme-3_css': 'base--theme-3.css',
'file_name_base--blueprint_css':'base--theme-blueprint.css'
};
// write
// =====
var
_body = $R.document.getElementsByTagName('body')[0],
_component__next_pages_container_element = $R.document.createElement('div'),
_component__in_page_css_element = $R.document.createElement('style'),
_component__in_page_css_text = ''
+ '#next_pages_container { '
+ 'width: 5px; hight: 5px; '
+ 'position: absolute; '
+ 'top: -100px; left: -100px; '
+ 'z-index: 2147483647 !important; '
+ '} '
;
if(!_body) {
_body = $R.document.getElementsByTagName("frameset")[0];
}
// css
// ===
_component__in_page_css_element.setAttribute('id', '_clearly_component__css');
_component__in_page_css_element.setAttribute('type', 'text/css');
if (_component__in_page_css_element.styleSheet) { _component__in_page_css_element.styleSheet.cssText = _component__in_page_css_text; }
else { _component__in_page_css_element.appendChild(document.createTextNode(_component__in_page_css_text)); }
_body.appendChild(_component__in_page_css_element);
// next pages
// ==========
_component__next_pages_container_element.setAttribute('id', '_clearly_component__next_pages_container');
_body.appendChild(_component__next_pages_container_element);
$R.$nextPages = $('#_clearly_component__next_pages_container');
// bulk
// ====
// debug
// =====
// defaults to false
if ($R.debug); else { $R.debug = false; }
// make it faster -- when not debugging
// ==============
if (!($R.debug))
{
$R.debugRemember = {};
$R.writeLog = function () { return false; };
$R.log = function () { return false; };
$R.debugTimerStart = function () { return false; };
$R.debugTimerEnd = function () { return false; };
$R.debugPrint = function () { return false; };
$R.printDebugOutput = function () { return false; };
$R.debugOutline = function () { return false; };
}
else
{
// remember stuff
$R.debugRemember = {};
// vars
// ====
$R.debugStuff = [];
$R.debugTimers = [];
// write log
// =========
$R.initializeWriteLogFunction = function ()
{
switch (true)
{
case (!(!($R.win.console && $R.win.console.log))):
$R.writeLog = function (msg) { $R.win.console.log(msg); };
break;
case (!(!($R.win.opera && $R.win.opera.postError))):
$R.writeLog = function (msg) { $R.win.opera.postError(msg); };
break;
default:
$R.writeLog = function (msg) {};
break;
}
};
// log
// ===
$R.initializeWriteLogFunction();
$R.log = function ()
{
if ($R.debug); else { return; }
for (var i=0, il=arguments.length; i<il ; i++)
{ $R.writeLog(arguments[i]); }
$R.writeLog('-----------------------------------------');
};
// outline
// =======
$R.debugOutline = function (_element, _category, _reason)
{
switch (true)
{
case (!$R.debug):
case (!(_element.nodeType === 1)):
case (!(_element.tagName > '')):
case (_element.tagName.toLowerCase() == 'onject'):
case (_element.tagName.toLowerCase() == 'embed'):
return;
}
var
_outline = '#ff5500',
_background = 'rgba(255, 85, 0, 0.5)'
;
// choose
switch (true)
{
case (_category == 'target' && _reason == 'first'):
_outline = '#00cc00';
_background = 'rgba(0, 255, 0, 0.5)';
break;
case (_category == 'target' && _reason == 'second'):
_outline = '#0000cc';
_background = 'rgba(0, 0, 255, 0.5)';
break;
// =====
case (_category == 'target' && _reason == 'next-page'):
_outline = '#FF80C0';
_background = 'rgba(255, 128, 192, 0.5)';
break;
case (_category == 'target' && _reason == 'add-above'):
_outline = '#804000';
_background = 'rgba(128, 64, 0, 0.5)';
break;
// =====
case (_category == 'clean-before' && _reason == 'floating'):
_outline = '#808080';
_background = 'rgba(128, 128, 128, 0.5)';
break;
case (_category == 'clean-after' && _reason == 'missing-density'):
_outline = '#C0C0C0';
_background = 'rgba(192, 192, 192, 0.5)';
break;
case (_category == 'clean-after' || _category == 'clean-before'):
_outline = '#000000';
_background = 'rgba(0, 0, 0, 0.5)';
break;
}
// do
$(_element).attr('readable__outline', (_category + ': ' + _reason));
$(_element).css({
'outline': '5px solid ' + _outline,
'background-color': '' + _background
});
};
$R.debugBackground = function (_element, _category, _reason)
{
if ($R.debug); else { return; }
switch (true)
{
case (!(_element.nodeType === 1)):
case (!(_element.tagName > '')):
case (_element.tagName.toLowerCase() == 'onject'):
case (_element.tagName.toLowerCase() == 'embed'):
// don't outline
break;
default:
var _color = 'transparent';
switch (true)
{
case (_category == 'target' && _reason == 'first'): _color = ''; break;
case (_category == 'target' && _reason == 'second'): _color = ''; break;
case (_category == 'target' && _reason == 'next-page'): _color = '#FF80C0'; break;
case (_category == 'target' && _reason == 'add-above'): _color = '#804000'; break;
case (_category == 'clean-before' && _reason == 'floating'): _color = '#808080'; break;
case (_category == 'clean-after' && _reason == 'missing-density'): _color = '#C0C0C0'; break;
case (_category == 'clean-after' || _category == 'clean-before'): _color = '#000000'; break;
}
$(_element).css('outline','5px solid '+_color);
$(_element).attr('readable__outline', (_category + ': ' + _reason));
break;
}
};
// timers
// ======
$R.debugTimerStart = function (timerName)
{
$R.debugTimers.push({
'name': timerName,
'start': (new Date()).getTime()
});
};
$R.debugTimerEnd = function ()
{
var _t = $R.debugTimers.pop(), _time = ((new Date()).getTime() - _t.start);
$R.log('TIMER / '+_t.name+': ' + _time);
return _time;
};
// output -- will be shown in Show function
// ======
$R.debugPrint = function (_key, _value)
{ $R.debugStuff[_key] = _value; };
$R.printDebugOutput = function ()
{
// return
if ($R.debug); else { return; }
if ($R.customScript) { return; }
// first
var _first =
[
'Language',
'ExploreAndGetStuff',
'ProcessFirst',
'ProcessSecond',
'BuildHTML',
'BuildHTMLPregs',
'PointsFirst',
'PointsSecond',
'Target',
'NextPage',
'TitleSource'
];
// get and clean
_$debug = $('#debugOutput');
_$debug.html('');
// write
var _debug_write = function (_key, _value)
{
_$debug.append(''
+ '
<tr>'
+ '<td class="caption">'
+ _key
+ '</td>'
+ '<td id="debugOutput__value__'+_key+'" class="value">'
+ _value
+ '</td>'
+ '</tr>
'
);
}
// first
for (var i=0, _i=_first.length; i<_i; i++)
{ _debug_write(_first[i], $R.debugStuff[_first[i]]); delete($R.debugStuff[_first[i]]); }
// the rest
for (var _k in $R.debugStuff)
{ _debug_write(_k, $R.debugStuff[_k]); }
// end; stop
$R.debugPrint = function () {};
$R.printDebugOutput = function () {};
};
// scriptable scrolling
$R.debugScroll__before1 = function () { $R.win.scrollTo(0, 0); };
$R.debugScroll__before2 = function () { $R.win.scrollTo(0, $R.$win.height()); };
$R.debugScroll__before3 = function () { if ($($R.debugRemember['theTarget']).height() > 0) { $R.debugRemember['theTarget'].scrollIntoView(false); } else { $R.debugRemember['firstCandidate'].scrollIntoView(false); } $R.win.scrollBy(0, 100); };
$R.debugScroll__after1 = function () { window.scrollTo(0, 0); };
$R.debugScroll__after2 = function () { window.scrollTo(0, $R.$win.height()); };
$R.debugScroll__after3 = function () { $('#page1').get(0).scrollIntoView(false); window.scrollBy(0, 100); };
}
$R.debug = false;
// environment
// ===========
// environtment
// ============
$R.mac = (!$R.iOS && ($R.win.navigator.userAgent.match(/Macintosh/i) != null));
// get browser
// var -- gets filled in
// ===
var __the_browser = 'unknown';
// possible values -- in this order
// ===============
/*
firefox
safari
chrome
internet_explorer
opera
iphone
ipad
android
dolphin
firefox_mobile
chrome_mobile
windows_phone
*/
// doing work
// ==========
__the_browser = (function ()
{
// ua string
// =========
var _ua = window.navigator.userAgent.toLowerCase();
// cases
// =====
if ((_ua.indexOf('windows phone') > -1)) { return 'windows_phone'; }
if ((_ua.indexOf('chrome') > -1) && (_ua.indexOf('android') > -1)) { return 'chrome_mobile'; }
if ((_ua.indexOf('firefox') > -1) && (_ua.indexOf('fennec') > -1)) { return 'firefox_mobile'; }
if ((_ua.indexOf('dolfin') > -1) || (_ua.indexOf('dolphin') > -1)) { return 'dolphin'; }
if ((_ua.indexOf('android') > -1)) { return 'android'; }
if ((_ua.indexOf('ipad') > -1)) { return 'ipad'; }
if ((_ua.indexOf('iphone') > -1)) { return 'iphone'; }
if ($.browser.opera) { return 'opera'; }
if ($.browser.msie) { return 'internet_explorer'; }
if ($.browser.webkit && (_ua.indexOf('chrome') > -1)) { return 'chrome'; }
if ($.browser.webkit && (_ua.indexOf('safari') > -1)) { return 'safari'; }
if ($.browser.mozilla) { return 'firefox'; }
})();
$R.browser = __the_browser;
// language specific stuff
// =======================
// default
$R.language = 'general';
// the text - start with title
var _test_text = ' ' + $R.document.title;
// add couple of random paragraphs, divs
var
_ps = $R.document.getElementsByTagName('p'),
_ds = $R.document.getElementsByTagName('div')
;
// add
for (var i=0; i<5; i++) { _test_text += ' ' + $(_ps[Math.floor(Math.random()*_ps.length)]).text(); }
for (var i=0; i<5; i++) { _test_text += ' ' + $(_ds[Math.floor(Math.random()*_ds.length)]).text(); }
// check
switch (true)
{
// case ($R.win.location.host.match(/\.jp$/i) != null):
// case ($R.win.location.host.match(/\.cn$/i) != null):
// case ($R.win.location.host.match(/\.tw$/i) != null):
// case ($R.win.location.host.match(/\.hk$/i) != null):
// case ($R.win.location.host.match(/\.kr$/i) != null):
case (_test_text.match(/([\u3000])/gi) != null):
case (_test_text.match(/([\u3001])/gi) != null):
case (_test_text.match(/([\u3002])/gi) != null):
case (_test_text.match(/([\u301C])/gi) != null):
$R.language = 'cjk';
break;
}
// in case we stop
$R.debugPrint('Language', $R.language);
// rtl
// ===
// var
// ===
$R.rtl = false;
// functions
// =========
$R.makeRTL = function ()
{
// set
$R.rtl = true;
// as component; return
if ($R.component) { return; }
$('#curtain__rtl__radio__rtl').get(0).checked = true;
$('#curtain__rtl__radio__ltr').get(0).checked = false;
$('html')
.attr('dir', 'rtl')
.addClass('couldBeRTL')
.addClass('rtl');
$R.$pages
.attr('dir', 'rtl')
.addClass('rtl');
};
$R.makeNotRTL = function ()
{
// set
$R.rtl = false;
// as component; return
if ($R.component) { return; }
$('#curtain__rtl__radio__rtl').get(0).checked = false;
$('#curtain__rtl__radio__ltr').get(0).checked = true;
$('html')
.attr('dir', '')
.removeClass('rtl');
$R.$pages
.attr('dir', '')
.removeClass('rtl');
};
// detect
// ======
(function ()
{
// definitely rtl
$R.$document.find('html, body').each(function (_i, _e)
{
switch (true) {
case ($(_e).attr('dir') == 'rtl'):
case ($(_e).css('direction') == 'rtl'):
case ($(_e).attr('lang') == 'he'):
case ($(_e).attr('lang') == 'he-il'):
case ($(_e).attr('lang') == 'ar'):
case ($(_e).attr('lang') == 'ur'):
$R.makeRTL();
return false;
}
});
// maybe rtl
// =========
if ($R.component); else
{
if ((!$R.rtl) && ($R.$document.find("div[dir='rtl'], table[dir='rtl'], td[dir='rtl']").length > 0))
{ $('html').addClass('couldBeRTL'); }
}
})();
// events
// ======
if ($R.component); else
{
$('#curtain__rtl__radio__rtl').change(function(){ $R.makeRTL(); return false; });
$('#curtain__rtl__radio__ltr').change(function(){ $R.makeNotRTL(); return false; });
}
// measure text
// ============
// asian languages
// ===============
// http://msdn.microsoft.com/en-us/goglobal/bb688158
// http://en.wikipedia.org/wiki/Japanese_punctuation
// http://en.wikipedia.org/wiki/Japanese_typographic_symbols
// http://unicode.org/charts/PDF/U3000.pdf
// CJK: Chnese, Japanese, Korean -- HAN character set
// length
// ======
$R.measureText__getTextLength = function (_the_text)
{
var _text = _the_text;
_text = _text.replace(/[\s\n\r]+/gi, '');
//_text = _text.replace(/\d+/, '');
return _text.length;
};
// word count
// ==========
$R.measureText__getWordCount = function (_the_text)
{
var _text = _the_text;
// do stuff
// ========
_text = _text.replace(/[\s\n\r]+/gi, ' ');
_text = _text.replace(/([.,?!:;()\[\]'""-])/gi, ' $1 ');
_text = _text.replace(/([\u3000])/gi, '[=words(1)]');
_text = _text.replace(/([\u3001])/gi, '[=words(2)]');
_text = _text.replace(/([\u3002])/gi, '[=words(4)]');
_text = _text.replace(/([\u301C])/gi, '[=words(2)]');
_text = _text.replace(/([\u2026|\u2025])/gi, '[=words(2)]');
_text = _text.replace(/([\u30FB\uFF65])/gi, '[=words(1)]');
_text = _text.replace(/([\u300C\u300D])/gi, '[=words(1)]');
_text = _text.replace(/([\u300E\u300F])/gi, '[=words(1)]');
_text = _text.replace(/([\u3014\u3015])/gi, '[=words(1)]');
_text = _text.replace(/([\u3008\u3009])/gi, '[=words(1)]');
_text = _text.replace(/([\u300A\u300B])/gi, '[=words(1)]');
_text = _text.replace(/([\u3010\u3011])/gi, '[=words(1)]');
_text = _text.replace(/([\u3016\u3017])/gi, '[=words(1)]');
_text = _text.replace(/([\u3018\u3019])/gi, '[=words(1)]');
_text = _text.replace(/([\u301A\u301B])/gi, '[=words(1)]');
_text = _text.replace(/([\u301D\u301E\u301F])/gi, '[=words(1)]');
_text = _text.replace(/([\u30A0])/gi, '[=words(1)]');
// count
// =====
var
_count = 0,
_words_match = _text.match(/([^\s\d]{3,})/gi)
;
// add match
_count += (_words_match != null ? _words_match.length : 0);
// add manual count
_text.replace(/\[=words\((\d)\)\]/, function (_match, _plus) { _count += (5 * parseInt(_plus)); });
// return
// ======
return _count;
};
// levenshtein
// ===========
$R.levenshteinDistance = function (str1, str2)
{
var l1 = str1.length, l2 = str2.length;
if (Math.min(l1, l2) === 0)
{ return Math.max(l1, l2); }
var i = 0, j = 0, d = [];
for (i = 0 ; i <= l1 ; i++)
{
d[i] = [];
d[i][0] = i;
}
for (j = 0 ; j <= l2 ; j++)
{ d[0][j] = j; }
for (i = 1 ; i <= l1 ; i++)
{
for (j = 1 ; j <= l2 ; j++)
{
d[i][j] = Math.min
(
d[i - 1][j] + 1,
d[i][j - 1] + 1,
d[i - 1][j - 1] + (str1.charAt(i - 1) === str2.charAt(j - 1) ? 0 : 1)
);
}
}
return d[l1][l2];
};
// content
// =======
$R.footnotedLinksCount = 0;
$R.getContent = function ()
{
// homepage?
if ($R.win.location.href == ($R.win.location.protocol + '//' + $R.win.location.host + '/'))
{ $('html').addClass('showTips'); }
// selection or whole
switch (true)
{
case ($R.getContent__manualSelection()):
case ($R.getContent__find()):
break;
default:
break;
}
// debug
$R.printDebugOutput();
// show content
$R.showContent();
};
$R.getContent__manualSelection = function ()
{
var
_selection = $R.sel.getSelection($R.win),
_range = $R.sel.getRange(_selection),
_html = $R.sel.getRangeHTML(_range),
_text = $R.sel.getRangeText(_range)
;
if (_html > '' && _text > ''); else
{
_html = null;
_text = null;
$R.$document.find('frame, iframe').each(function (_i, _e)
{
if (_e.getAttribute('id') == 'readable_iframe') { return; }
try
{
var
__doc = $(_e).contents().get(0),
__win = $R.sel.getWindowFromDocument(__doc),
__selection = $R.sel.getSelection(__win),
__range = $R.sel.getRange(__selection),
__html = $R.sel.getRangeHTML(__range),
__text = $R.sel.getRangeText(__range)
;
if (__html > '' && __text > '')
{
_html = __html;
_text = __text;
// stop the each
return false;
}
}
catch(e) { }
});
}
// haven't found anything
if (_html > '' && _text > ''); else { return false; }
// probably selected something by mistake
if ($R.measureText__getTextLength(_text) > (65 * 3 * 1.5)); else { return false; }
// display
// =======
$R.$pages.html('');
$R.displayPageHTML(_html, 1, 'selection');
// return true
return true;
};
// functions
// =========
$R.sel = {};
$R.sel.getWindowFromDocument = function (theDocument)
{
if (theDocument); else { return null; }
if ('defaultView' in theDocument) {
arguments.calee = function (theDocument) {
if (theDocument); else { return null; }
return theDocument.defaultView;
};
}
else if ('parentWindow' in theDocument) {
arguments.calee = function (theDocument) {
if (theDocument); else { return null; }
return theDocument.parentWindow;
};
}
else {
arguments.calee = function (theDocument) {
return null;
};
}
return arguments.calee(theDocument);
};
$R.sel.getSelection = function (theWindow)
{
if (theWindow); else { return null; }
if ('getSelection' in theWindow) {
arguments.calee = function (theWindow) {
if (theWindow); else { return null; }
return theWindow.getSelection();
};
}
else if ('selection' in theWindow.document) {
arguments.calee = function (theWindow) {
if (theWindow); else { return null; }
return theWindow.document.selection;
};
}
else {
arguments.calee = function (theWindow) {
return null;
};
}
return arguments.calee(theWindow);
};
$R.sel.getRange = function (selection)
{
if (selection); else { return null; }
if ('getRangeAt' in selection) {
arguments.calee = function (selection) {
if (selection); else { return null; }
if (selection.rangeCount > 0) { return selection.getRangeAt(0); }
else { return null; }
// doesn't work in old versions of safari
// ... I don't care
};
}
else if ('createRange' in selection) {
arguments.calee = function (selection) {
if (selection); else { return null; }
return selection.createRange();
};
}
else {
arguments.calee = function (selection) {
return null;
};
}
return arguments.calee(selection);
};
$R.sel.getRangeHTML = function (range)
{
if (range); else { return null; }
if ('htmlText' in range) {
arguments.calee = function (range) {
if (range); else { return null; }
return range.htmlText;
};
}
else if ('surroundContents' in range) {
arguments.calee = function (range) {
if (range); else { return null; }
var dummy = range.commonAncestorContainer.ownerDocument.createElement("div");
dummy.appendChild(range.cloneContents());
return dummy.innerHTML;
};
}
else {
arguments.calee = function (range) {
return null;
};
}
return arguments.calee(range);
};
$R.sel.getRangeText = function (range)
{
if (range); else { return null; }
if ('text' in range) {
arguments.calee = function (range) {
if (range); else { return null; }
return range.text;
};
}
else if ('surroundContents' in range) {
arguments.calee = function (range) {
if (range); else { return null; }
var dummy = range.commonAncestorContainer.ownerDocument.createElement("div");
dummy.appendChild(range.cloneContents());
return dummy.textContent;
};
}
else {
arguments.calee = function (range) {
return null;
};
}
return arguments.calee(range);
};
// options
// =======
$R.parsingOptions =
{
'_elements_ignore': '|button|input|select|textarea|optgroup|command|datalist|--|frame|frameset|noframes|--|style|link|script|noscript|--|canvas|applet|map|--|marquee|area|base|',
'_elements_ignore_tag': '|form|fieldset|details|dir|--|center|font|span|',
'_elements_self_closing': '|br|hr|--|img|--|col|--|source|--|embed|param|--|iframe|',
'_elements_visible': '|article|section|--|ul|ol|li|dd|--|table|tr|td|--|div|--|p|--|h1|h2|h3|h4|h5|h6|--|span|',
'_elements_too_much_content': '|b|i|em|strong|--|h1|h2|h3|h4|h5|--|td|',
'_elements_container': '|body|--|article|section|--|div|--|td|--|li|--|dd|dt|',
'_elements_link_density': '|div|--|table|ul|ol|--|section|aside|header|',
'_elements_floating': '|div|--|table|',
'_elements_above_target_ignore':'|br|--|ul|ol|dl|--|table|',
'_elements_keep_attributes':
{
'a': ['href', 'title', 'name'],
'img': ['src', 'width', 'height', 'alt', 'title'],
'video': ['src', 'width', 'height', 'poster', 'audio', 'preload', 'autoplay', 'loop', 'controls'],
'audio': ['src', 'preload', 'autoplay', 'loop', 'controls'],
'source': ['src', 'type'],
'object': ['data', 'type', 'width', 'height', 'classid', 'codebase', 'codetype'],
'param': ['name', 'value'],
'embed': ['src', 'type', 'width', 'height', 'flashvars', 'allowscriptaccess', 'allowfullscreen', 'bgcolor'],
'iframe': ['src', 'width', 'height', 'frameborder', 'scrolling'],
'td': ['colspan', 'rowspan'],
'th': ['colspan', 'rowspan']
}
};
// next page keywords -- (?? charCodeAt() > 127)
// ==================
$R.nextPage__captionKeywords =
[
/* english */
'next page', 'next',
/* german */
'vorwärts', 'weiter',
/* japanese */
'次へ'
];
$R.nextPage__captionKeywords__not =
[
/* english */
'article', 'story', 'post', 'comment', 'section', 'chapter'
];
// skip links
// ==========
$R.skipStuffFromDomains__links =
[
'doubleclick.net',
'fastclick.net',
'adbrite.com',
'adbureau.net',
'admob.com',
'bannersxchange.com',
'buysellads.com',
'impact-ad.jp',
'atdmt.com',
'advertising.com',
'itmedia.jp',
'microad.jp',
'serving-sys.com',
'adplan-ds.com'
];
// skip images
// ===========
$R.skipStuffFromDomain__images =
[
'googlesyndication.com',
'fastclick.net',
'.2mdn.net',
'de17a.com',
'content.aimatch.com',
'bannersxchange.com',
'buysellads.com',
'impact-ad.jp',
'atdmt.com',
'advertising.com',
'itmedia.jp',
'microad.jp',
'serving-sys.com',
'adplan-ds.com'
];
// keep video
// ==========
$R.keepStuffFromDomain__video =
[
'youtube.com',
'youtube-nocookie.com',
'vimeo.com',
'hulu.com',
'yahoo.com',
'flickr.com',
'newsnetz.ch'
];
$R.getContent__exploreNodeAndGetStuff = function (_nodeToExplore, _justExploring)
{
var
_global__element_index = 0,
_global__inside_link = false,
_global__inside_link__element_index = 0,
_global__length__above_plain_text = 0,
_global__count__above_plain_words = 0,
_global__length__above_links_text = 0,
_global__count__above_links_words = 0,
_global__count__above_candidates = 0,
_global__count__above_containers = 0,
_global__above__plain_text = '',
_global__above__links_text = '',
_return__containers = [],
_return__candidates = [],
_return__links = []
;
// recursive function
// ==================
var _recursive = function (_node)
{
// increment index
// starts with 1
_global__element_index++;
var
_tag_name = (_node.nodeType === 3 ? '#text' : ((_node.nodeType === 1 && _node.tagName && _node.tagName > '') ? _node.tagName.toLowerCase() : '#invalid')),
_result =
{
'__index': _global__element_index,
'__node': _node,
'_is__container': ($R.parsingOptions._elements_container.indexOf('|'+_tag_name+'|') > -1),
'_is__candidate': false,
'_is__text': false,
'_is__link': false,
'_is__link_skip': false,
'_is__image_small': false,
'_is__image_medium': false,
'_is__image_large': false,
'_is__image_skip': false,
'_debug__above__plain_text': _global__above__plain_text,
'_debug__above__links_text': _global__above__links_text,
'_length__above_plain_text': _global__length__above_plain_text,
'_count__above_plain_words': _global__count__above_plain_words,
'_length__above_links_text': _global__length__above_links_text,
'_count__above_links_words': _global__count__above_links_words,
'_length__above_all_text': (_global__length__above_plain_text + _global__length__above_links_text),
'_count__above_all_words': (_global__count__above_plain_words + _global__count__above_links_words),
'_count__above_candidates': _global__count__above_candidates,
'_count__above_containers': _global__count__above_containers,
'_length__plain_text': 0,
'_count__plain_words': 0,
'_length__links_text': 0,
'_count__links_words': 0,
'_length__all_text': 0,
'_count__all_words': 0,
'_count__containers': 0,
'_count__candidates': 0,
'_count__links': 0,
'_count__links_skip': 0,
'_count__images_small': 0,
'_count__images_medium': 0,
'_count__images_large': 0,
'_count__images_skip': 0
};
// fast return
// ===========
switch (true)
{
case ((_tag_name == '#invalid')):
case (($R.parsingOptions._elements_ignore.indexOf('|'+_tag_name+'|') > -1)):
return;
case (($R.parsingOptions._elements_visible.indexOf('|'+_tag_name+'|') > -1)):
// included inline
// _node, _tag_name must be defined
// will return, if node is hidden
switch (true)
{
case (_node.offsetWidth > 0):
case (_node.offsetHeight > 0):
break;
default:
switch (true)
{
case (_node.offsetLeft > 0):
case (_node.offsetTop > 0):
break;
default:
// exclude inline DIVs -- which, stupidly, don't have a width/height
if ((_tag_name == 'div') && ((_node.style.display || $.css( _node, "display" )) == 'inline'))
{ break; }
// it's hidden; exit current scope
return;
}
break;
}
break;
// self-closing -- with some exceptions
case ($R.parsingOptions._elements_self_closing.indexOf('|'+_tag_name+'|') > -1):
switch (true)
{
case ((_tag_name == 'img')): break;
default: return;
}
break;
}
// do stuff
// ========
switch (true)
{
// text node
// =========
case ((_tag_name == '#text')):
// mark
_result._is__text = true;
// get
var _nodeText = _node.nodeValue;
// result
_result._length__plain_text = $R.measureText__getTextLength(_nodeText);
_result._count__plain_words = $R.measureText__getWordCount(_nodeText);
if (_global__inside_link)
{
_global__length__above_links_text += _result._length__plain_text;
_global__count__above_links_words += _result._count__plain_words;
if (false && $R.debug) { _global__above__links_text += ' ' + _nodeText; }
}
else
{
_global__length__above_plain_text += _result._length__plain_text;
_global__count__above_plain_words += _result._count__plain_words;
if (false && $R.debug) { _global__above__plain_text += ' ' + _nodeText; }
}
// return text
return _result;
// link
// ====
case (_tag_name == 'a'):
var _href = "";
try {
_href = _node.href;
} catch(e) {
Evernote.Logger.warn("Clearly: failed to get href of link element" + e);
}
// sanity
if (_href > ''); else { break; }
if (_href.indexOf); else { break; }
_result._is__link = true;
// skip
for (var i=0, _i=$R.skipStuffFromDomains__links.length; i<_i; i++)
{
if (_node.href.indexOf($R.skipStuffFromDomains__links[i]) > -1)
{ _result._is__link_skip = true; break; }
}
// inside link
if (_global__inside_link); else
{
_global__inside_link = true;
_global__inside_link__element_index = _result.__index;
}
// done
_return__links.push(_result);
break;
// image
// =====
case (_tag_name == 'img'):
// skip
// ====
if (_node.src && _node.src.indexOf)
{
for (var i=0, _i=$R.skipStuffFromDomain__images.length; i<_i; i++)
{
if (_node.src.indexOf($R.skipStuffFromDomain__images[i]) > -1)
{ _result._is__image_skip = true; break; }
}
}
// size
// ====
var _width = $(_node).width(), _height = $(_node).height();
switch (true)
{
case ((_width * _height) >= 50000):
case ((_width >= 350) && (_height >= 75)):
_result._is__image_large = true;
break;
case ((_width * _height) >= 20000):
case ((_width >= 150) && (_height >= 150)):
_result._is__image_medium = true;
break;
case ((_width <= 5) && (_height <= 5)):
_result._is__image_skip = true;
break;
default:
_result._is__image_small = true;
break;
}
break;
}
// child nodes
// ===========
for (var i=0, _i=_node.childNodes.length; i<_i; i++)
{
var
_child = _node.childNodes[i],
_child_result = _recursive(_child)
;
// if false, continue
// ==================
if (_child_result); else { continue; }
// add to result
// =============
_result._count__links += _child_result._count__links + (_child_result._is__link ? 1 : 0);
_result._count__links_skip += _child_result._count__links_skip + (_child_result._is__link_skip ? 1 : 0);
_result._count__images_small += _child_result._count__images_small + (_child_result._is__image_small ? 1 : 0);
_result._count__images_medium += _child_result._count__images_medium + (_child_result._is__image_medium ? 1 : 0);
_result._count__images_large += _child_result._count__images_large + (_child_result._is__image_large ? 1 : 0);
_result._count__images_skip += _child_result._count__images_skip + (_child_result._is__image_skip ? 1 : 0);
_result._count__containers += _child_result._count__containers + (_child_result._is__container ? 1 : 0);
_result._count__candidates += _child_result._count__candidates + (_child_result._is__candidate ? 1 : 0);
_result._length__all_text += _child_result._length__plain_text + _child_result._length__links_text;
_result._count__all_words += _child_result._count__plain_words + _child_result._count__links_words;
// plain text / link text
// ======================
switch (true)
{
case (_child_result._is__link):
// no text to add
_result._length__links_text += (_child_result._length__plain_text + _child_result._length__links_text);
_result._count__links_words += (_child_result._count__plain_words + _child_result._count__links_words);
break;
default:
_result._length__plain_text += _child_result._length__plain_text;
_result._count__plain_words += _child_result._count__plain_words;
_result._length__links_text += _child_result._length__links_text;
_result._count__links_words += _child_result._count__links_words;
break;
}
}
// after child nodes
// =================
// mark as not in link anymore
// ===========================
if (true
&& (_result._is__link)
&& (_global__inside_link__element_index == _result.__index)
) {
_global__inside_link = false;
_global__inside_link__element_index = 0;
}
// add to containers
// =================
if (_result._is__container || ((_result.__index == 1) && (_justExploring == true)))
{
// add to containers
_return__containers.push(_result);
// increase above containers
if (_result._is__container) { _global__count__above_containers++; }
// add to candidates
if (_justExploring); else
{
switch (true)
{
case (($R.language != 'cjk') && ((_result._count__links * 2) >= _result._count__plain_words)): /* link ratio */
case (($R.language != 'cjk') && (_result._length__plain_text < (65 / 3))): /* text length */
case (($R.language != 'cjk') && (_result._count__plain_words < 5)): /* words */
case (($R.language == 'cjk') && (_result._length__plain_text < 10)): /* text length */
case (($R.language == 'cjk') && (_result._count__plain_words < 2)): /* words */
//case (_result._length__plain_text == 0): /* no text */
//case (_result._count__plain_words == 0): /* no words */
//case (($R.language == 'cjk') && ((_result._length__plain_text / 65 / 3) < 0.1)): /* paragrahs of 3 lines */
//case (($R.language != 'cjk') && ((_result._count__plain_words / 50) < 0.5)): /* paragraphs of 50 words */
// not a valid candidate
//if (_tag_name == 'div') { $R.log('bad candidate', _result.__node); }
break;
default:
// good candidate
_result._is__candidate = true;
_return__candidates.push(_result);
// increase above candidates
_global__count__above_candidates++;
break;
}
// special case for body -- if it was just skipped
// =====================
if ((_result.__index == 1) && !(_result._is__candidate))
{
_result._is__candidate = true;
_result._is__bad = true;
_return__candidates.push(_result);
}
}
}
// return
// ======
return _result;
};
// actually do it
// ==============
_recursive(_nodeToExplore);
// just exploring -- return first thing
// ==============
if (_justExploring) { return _return__containers.pop(); }
// return containers list
// ======================
return {
'_containers': _return__containers,
'_candidates': _return__candidates,
'_links': _return__links
};
};
$R.getContent__processCandidates = function (_candidatesToProcess)
{
// process this var
// ================
var _candidates = _candidatesToProcess;
// sort _candidates -- the lower in the dom, the closer to position 0
// ================
_candidates.sort(function (a, b)
{
switch (true)
{
case (a.__index < b.__index): return -1;
case (a.__index > b.__index): return 1;
default: return 0;
}
});
// get first
// =========
var _main = _candidates[0]
if ($R.debug) { $R.log('should be body', _main, _main.__node); }
// pieces of text
// and points computation
// ======================
for (var i=0, _i=_candidates.length; i<_i; i++)
{
// pieces
// ======
var
_count__pieces = 0,
_array__pieces = []
;
for (var k=i, _k=_candidates.length; k<_k; k++)
{
if (_candidates[k]._count__candidates > 0) { continue; }
if ($.contains(_candidates[i].__node, _candidates[k].__node)); else { continue; }
// store piece, if in debug mode
if ($R.debug) { _array__pieces.push(_candidates[k]); }
// incement pieces count
_count__pieces++;
}
// candidate details
// =================
_candidates[i]['__candidate_details'] = $R.getContent__computeDetailsForCandidate(_candidates[i], _main);
// pieces -- do this here because _main doesn't yet have a pieces count
// ======
// set pieces
_candidates[i]['_count__pieces'] = _count__pieces;
_candidates[i]['_array__pieces'] = _array__pieces;
// pieces ratio
_candidates[i]['__candidate_details']['_ratio__count__pieces_to_total_pieces'] = (_count__pieces / (_candidates[0]._count__pieces + 1));
// check some more
// ===============
/* switch (true)
{
case (($R.language != 'cjk') && (_candidates[i]['__candidate_details']['_ratio__length__links_text_to_plain_text'] > 1)):
case (($R.language != 'cjk') && (_candidates[i]['__candidate_details']['_ratio__count__links_words_to_plain_words'] > 1)):
_candidates[i]._is__bad = true;
break;
}*/
// points
// ======
_candidates[i].__points_history = $R.getContent__computePointsForCandidate(_candidates[i], _main);
_candidates[i].__points = _candidates[i].__points_history[0];
}
// sort _candidates -- the more points, the closer to position 0
// ================
_candidates.sort(function (a, b)
{
switch (true)
{
case (a.__points > b.__points): return -1;
case (a.__points < b.__points): return 1;
default: return 0;
}
});
// return
// ======
return _candidates;
};
$R.getContent__computeDetailsForCandidate = function (_e, _main)
{
var _r = {};
// bad candidate
// =============
if (_e._is__bad) { return _r; }
// paragraphs
// ==========
_r['_count__lines_of_65_characters'] = (_e._length__plain_text / 65);
_r['_count__paragraphs_of_3_lines'] = (_r._count__lines_of_65_characters / 3);
_r['_count__paragraphs_of_5_lines'] = (_r._count__lines_of_65_characters / 5);
_r['_count__paragraphs_of_50_words'] = (_e._count__plain_words / 50);
_r['_count__paragraphs_of_80_words'] = (_e._count__plain_words / 80);
// total text
// ==========
_r['_ratio__length__plain_text_to_total_plain_text'] = (_e._length__plain_text / _main._length__plain_text);
_r['_ratio__count__plain_words_to_total_plain_words'] = (_e._count__plain_words / _main._count__plain_words);
// links
// =====
_r['_ratio__length__links_text_to_plain_text'] = (_e._length__links_text / _e._length__plain_text);
_r['_ratio__count__links_words_to_plain_words'] = (_e._count__links_words / _e._count__plain_words);
_r['_ratio__length__links_text_to_all_text'] = (_e._length__links_text / _e._length__all_text);
_r['_ratio__count__links_words_to_all_words'] = (_e._count__links_words / _e._count__all_words);
_r['_ratio__length__links_text_to_total_links_text'] = (_e._length__links_text / (_main._length__links_text + 1));
_r['_ratio__count__links_words_to_total_links_words'] = (_e._count__links_words / (_main._count__links_words + 1));
_r['_ratio__count__links_to_total_links'] = (_e._count__links / (_main._count__links + 1));
_r['_ratio__count__links_to_plain_words'] = ((_e._count__links * 2) / _e._count__plain_words);
// text above
// ==========
var
_divide__candidates = Math.max(2, Math.ceil(_e._count__above_candidates * 0.5)),
_above_text = ((0
+ (_e._length__above_plain_text * 1)
+ (_e._length__above_plain_text / _divide__candidates)
) / 2),
_above_words = ((0
+ (_e._count__above_plain_words * 1)
+ (_e._count__above_plain_words / _divide__candidates)
) / 2)
;
_r['_ratio__length__above_plain_text_to_total_plain_text'] = (_above_text / _main._length__plain_text);
_r['_ratio__count__above_plain_words_to_total_plain_words'] = (_above_words / _main._count__plain_words);
// candidates
// ==========
_r['_ratio__count__candidates_to_total_candidates'] = (_e._count__candidates / (_main._count__candidates + 1));
_r['_ratio__count__containers_to_total_containers'] = (_e._count__containers / (_main._count__containers + 1));
// return
// ======
return _r;
};
$R.getContent__computePointsForCandidate = function (_e, _main)
{
var
_details = _e.__candidate_details,
_points_history = [],
_really_big = ((_main._length__plain_text / 65) > 250)
;
// bad candidate
if (_e._is__bad) { return [0]; }
// the basics
// ==========
_points_history.unshift(((0
+ (_details._count__paragraphs_of_3_lines)
+ (_details._count__paragraphs_of_5_lines * 1.5)
+ (_details._count__paragraphs_of_50_words)
+ (_details._count__paragraphs_of_80_words * 1.5)
+ (_e._count__images_large * 3)
- ((_e._count__images_skip + _e._count__images_small) * 0.5)
) * 1000));
// negative
if (_points_history[0] < 0) { return [0]; }
// candidates, containers, pieces
// ==============================
var
_divide__pieces = Math.max(5, Math.ceil(_e._count__pieces * 0.25)),
_divide__candidates = Math.max(5, Math.ceil(_e._count__candidates * 0.25)),
_divide__containers = Math.max(10, Math.ceil(_e._count__containers * 0.25))
;
_points_history.unshift(((0
+ (_points_history[0] * 3)
+ (_points_history[0] / _divide__pieces)
+ (_points_history[0] / _divide__candidates)
+ (_points_history[0] / _divide__containers)
) / 6));
// total text
// ==========
$R.getContent__computePointsForCandidate__do(0.10, 2, (1 - (1 - _details._ratio__length__plain_text_to_total_plain_text)), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 2, (1 - (1 - _details._ratio__count__plain_words_to_total_plain_words)), _points_history);
if (_really_big) {
$R.getContent__computePointsForCandidate__do(0.10, 4, (1 - (1 - _details._ratio__length__plain_text_to_total_plain_text)), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 4, (1 - (1 - _details._ratio__count__plain_words_to_total_plain_words)), _points_history);
}
// text above
// ==========
$R.getContent__computePointsForCandidate__do(0.10, 5, (1 - _details._ratio__length__above_plain_text_to_total_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 5, (1 - _details._ratio__count__above_plain_words_to_total_plain_words), _points_history);
if (_really_big) {
$R.getContent__computePointsForCandidate__do(0.10, 10, (1 - _details._ratio__length__above_plain_text_to_total_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 10, (1 - _details._ratio__count__above_plain_words_to_total_plain_words), _points_history);
}
// links outer
// ===========
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__length__links_text_to_total_links_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__count__links_words_to_total_links_words), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__count__links_to_total_links), _points_history);
// links inner
// ===========
var __lr = ($R.language == 'cjk' ? 0.75 : 0.50);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__length__links_text_to_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__count__links_words_to_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__length__links_text_to_all_text), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__count__links_words_to_all_words), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__count__links_to_plain_words), _points_history);
// candidates, containers, pieces
// ==============================
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__count__candidates_to_total_candidates), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__count__containers_to_total_containers), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details._ratio__count__pieces_to_total_pieces), _points_history);
// return -- will get [0] as the actual final points
// ======
return _points_history;
};
$R.getContent__processCandidatesSecond = function (_processedCandidates)
{
var
_candidates = _processedCandidates,
_main = _candidates[0]
;
// only get children of target
// ===========================
_candidates = $.map(_candidates, function (_element, _index)
{
switch (true)
{
case (!(_index > 0)):
case (!($.contains(_main.__node, _element.__node))):
return null;
default:
return _element;
}
});
// add main - to amke sure the result is never blank
_candidates.unshift(_main);
// sort _candidates -- the lower in the dom, the closer to position 0
// ================
_candidates.sort(function (a, b)
{
switch (true)
{
case (a.__index < b.__index): return -1;
case (a.__index > b.__index): return 1;
default: return 0;
}
});
// second candidate computation
// ============================
for (var i=0, _i=_candidates.length; i<_i; i++)
{
// additional numbers
// ==================
_candidates[i].__second_length__above_plain_text = (_candidates[i]._length__above_plain_text - _main._length__above_plain_text);
_candidates[i].__second_count__above_plain_words = (_candidates[i]._count__above_plain_words - _main._count__above_plain_words);
// candidate details
// =================
_candidates[i]['__candidate_details_second'] = $R.getContent__computeDetailsForCandidateSecond(_candidates[i], _main);
// check some more
// ===============
/* switch (true)
{
case (!(_candidates[i]['__candidate_details_second']['_ratio__count__plain_words_to_total_plain_words'] > 0.05)):
case (!(_candidates[i]['__candidate_details_second']['_ratio__length__plain_text_to_total_plain_text'] > 0.05)):
//case (!(_candidates[i]['__candidate_details_second']['_ratio__count__above_plain_words_to_total_plain_words'] < 0.1)):
//case (!(_candidates[i]['__candidate_details_second']['_ratio__length__above_plain_text_to_total_plain_text'] < 0.1)):
//case (_candidates[i]['__candidate_details_second']['_ratio__length__above_plain_text_to_plain_text'] > 1):
//case (_candidates[i]['__candidate_details_second']['_ratio__count__above_plain_words_to_plain_words'] > 1):
_candidates[i]._is__bad = true;
// wil set points to 0, in points computation function
break;
}*/
// points
// ======
_candidates[i].__points_history_second = $R.getContent__computePointsForCandidateSecond(_candidates[i], _main);
_candidates[i].__points_second = _candidates[i].__points_history_second[0];
}
// sort _candidates -- the more points, the closer to position 0
// ================
_candidates.sort(function (a, b)
{
switch (true)
{
case (a.__points_second > b.__points_second): return -1;
case (a.__points_second < b.__points_second): return 1;
default: return 0;
}
});
// return
// ======
return _candidates;
};
$R.getContent__computeDetailsForCandidateSecond = function (_e, _main)
{
var _r = {};
// bad candidate
// =============
if (_e._is__bad) { return _r; }
// total text
// ==========
_r['_ratio__length__plain_text_to_total_plain_text'] = (_e._length__plain_text / _main._length__plain_text);
_r['_ratio__count__plain_words_to_total_plain_words'] = (_e._count__plain_words / _main._count__plain_words);
// links
// =====
_r['_ratio__length__links_text_to_all_text'] = (_e._length__links_text / _e._length__all_text);
_r['_ratio__count__links_words_to_all_words'] = (_e._count__links_words / _e._count__all_words);
_r['_ratio__length__links_text_to_total_links_text'] = (_e._length__links_text / (_main._length__links_text + 1));
_r['_ratio__count__links_words_to_total_links_words'] = (_e._count__links_words / (_main._count__links_words + 1));
_r['_ratio__count__links_to_total_links'] = (_e._count__links / (_main._count__links + 1));
_r['_ratio__count__links_to_plain_words'] = ((_e._count__links * 2) / _e._count__plain_words);
// text above
// ==========
var
_divide__candidates = Math.max(2, Math.ceil((_e._count__above_candidates - _main._count__above_candidates) * 0.5)),
_above_text = ((0
+ (_e.__second_length__above_plain_text * 1)
+ (_e.__second_length__above_plain_text / _divide__candidates)
) / 2),
_above_words = ((0
+ (_e.__second_count__above_plain_words * 1)
+ (_e.__second_count__above_plain_words / _divide__candidates)
) / 2)
;
_r['_ratio__length__above_plain_text_to_total_plain_text'] = (_above_text / _main._length__plain_text);
_r['_ratio__count__above_plain_words_to_total_plain_words'] = (_above_words / _main._count__plain_words);
_r['_ratio__length__above_plain_text_to_plain_text'] = (_above_text / _e._length__plain_text);
_r['_ratio__count__above_plain_words_to_plain_words'] = (_above_words / _e._count__plain_words);
// candidates
// ==========
_r['_ratio__count__candidates_to_total_candidates'] = (Math.max(0, (_e._count__candidates - (_main._count__candidates * 0.25))) / (_main._count__candidates + 1));
_r['_ratio__count__containers_to_total_containers'] = (Math.max(0, (_e._count__containers - (_main._count__containers * 0.25))) / (_main._count__containers + 1));
_r['_ratio__count__pieces_to_total_pieces'] = (Math.max(0, (_e._count__pieces - (_main._count__pieces * 0.25))) / (_main._count__pieces + 1));
// return
// ======
return _r;
};
$R.getContent__computePointsForCandidateSecond = function (_e, _main)
{
var
_details = _e.__candidate_details,
_details_second = _e.__candidate_details_second,
_points_history = []
;
// bad candidate
if (_e._is__bad) { return [0]; }
// get initial points
// ==================
_points_history.unshift(_e.__points_history[(_e.__points_history.length-1)]);
// candidates, containers, pieces
// ==============================
var
_divide__pieces = Math.max(5, Math.ceil(_e._count__pieces * 0.25)),
_divide__candidates = Math.max(5, Math.ceil(_e._count__candidates * 0.25)),
_divide__containers = Math.max(10, Math.ceil(_e._count__containers * 0.25))
;
_points_history.unshift(((0
+ (_points_history[0] * 3)
+ ((_points_history[0] / _divide__pieces) * 2)
+ ((_points_history[0] / _divide__candidates) * 2)
+ ((_points_history[0] / _divide__containers) * 2)
) / 9));
// total text
// ==========
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - (1 - _details_second._ratio__length__plain_text_to_total_plain_text)), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - (1 - _details_second._ratio__count__plain_words_to_total_plain_words)), _points_history);
// text above
// ==========
var __ar = ($R.language == 'cjk' ? 0.50 : 0.10);
$R.getContent__computePointsForCandidate__do(__ar, 1, (1 - _details_second._ratio__length__above_plain_text_to_total_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(__ar, 1, (1 - _details_second._ratio__count__above_plain_words_to_total_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(__ar, 1, (1 - _details_second._ratio__length__above_plain_text_to_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(__ar, 1, (1 - _details_second._ratio__count__above_plain_words_to_plain_words), _points_history);
// links outer
// ===========
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details_second._ratio__count__links_to_total_links), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details_second._ratio__length__links_text_to_total_links_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - _details_second._ratio__count__links_words_to_total_links_words), _points_history);
// links inner
// ===========
var __lr = ($R.language == 'cjk' ? 0.75 : 0.50);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__length__links_text_to_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details._ratio__count__links_words_to_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details_second._ratio__length__links_text_to_all_text), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details_second._ratio__count__links_words_to_all_words), _points_history);
$R.getContent__computePointsForCandidate__do(__lr, 1, (1 - _details_second._ratio__count__links_to_plain_words), _points_history);
// candidates, containers, pieces
// ==============================
$R.getContent__computePointsForCandidate__do(0.10, 2, (1 - _details_second._ratio__count__candidates_to_total_candidates), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 2, (1 - _details_second._ratio__count__containers_to_total_containers), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 2, (1 - _details_second._ratio__count__pieces_to_total_pieces), _points_history);
// return -- will get [0] as the actual final points
// ======
return _points_history;
};
$R.getContent__computePointsForCandidateThird = function (_e, _main)
{
var
_details = _e.__candidate_details,
_details_second = _e.__candidate_details_second,
_points_history = []
;
// bad candidate
if (_e._is__bad) { return [0]; }
// get initial points
// ==================
_points_history.unshift(_e.__points_history[(_e.__points_history.length-1)]);
// candidates, containers, pieces
// ==============================
var
_divide__pieces = Math.max(2, Math.ceil(_e._count__pieces * 0.25)),
_divide__candidates = Math.max(2, Math.ceil(_e._count__candidates * 0.25)),
_divide__containers = Math.max(4, Math.ceil(_e._count__containers * 0.25))
;
_points_history.unshift(((0
+ (_points_history[0] * 3)
+ ((_points_history[0] / _divide__pieces) * 2)
+ ((_points_history[0] / _divide__candidates) * 2)
+ ((_points_history[0] / _divide__containers) * 2)
) / 9));
// total text
// ==========
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - (1 - _details_second._ratio__length__plain_text_to_total_plain_text)), _points_history);
$R.getContent__computePointsForCandidate__do(0.75, 1, (1 - (1 - _details_second._ratio__count__plain_words_to_total_plain_words)), _points_history);
// text above
// ==========
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__length__above_plain_text_to_total_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__above_plain_words_to_total_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 1, (1 - _details_second._ratio__length__above_plain_text_to_total_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 1, (1 - _details_second._ratio__count__above_plain_words_to_total_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 1, (1 - _details_second._ratio__length__above_plain_text_to_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.10, 1, (1 - _details_second._ratio__count__above_plain_words_to_plain_words), _points_history);
// links inner
// ===========
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__length__links_text_to_all_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__links_words_to_all_words), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__length__links_text_to_plain_text), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__links_words_to_plain_words), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__links_to_plain_words), _points_history);
// candidates, containers, pieces
// ==============================
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__candidates_to_total_candidates), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__containers_to_total_containers), _points_history);
$R.getContent__computePointsForCandidate__do(0.50, 1, (1 - _details._ratio__count__pieces_to_total_pieces), _points_history);
// return -- will get [0] as the actual final points
// ======
return _points_history;
};
$R.getContent__computePointsForCandidate__do = function (_ratio_remaining, _power, _ratio, _points_history)
{
var
_points_remaining = (_points_history[0] * _ratio_remaining),
_points_to_compute = (_points_history[0] - _points_remaining)
;
if (_ratio < 0)
{
//_points_return = (0.75 * _points_remaining);
_points_return = _points_remaining;
}
else
{
_points_return = 0
+ _points_remaining
+ (_points_to_compute * Math.pow(_ratio, _power))
;
}
// add
_points_history.unshift(_points_return);
};
$R.getContent__buildHTMLForNode = function (_nodeToBuildHTMLFor, _custom_mode)
{
var
_global__element_index = 0,
_global__the_html = '',
_global__exploreNodeToBuildHTMLFor = $R.getContent__exploreNodeAndGetStuff(_nodeToBuildHTMLFor, true)
;
// custom
// ======
switch (_custom_mode)
{
case 'above-the-target':
_global__exploreNodeToBuildHTMLFor = false;
break;
}
// recursive function
// ==================
var _recursive = function (_node)
{
// increment index -- starts with 1
// ===============
_global__element_index++;
// vars
// ====
var
_explored = false,
_tag_name = (_node.nodeType === 3 ? '#text' : ((_node.nodeType === 1 && _node.tagName && _node.tagName > '') ? _node.tagName.toLowerCase() : '#invalid')),
_pos__start__before = 0,
_pos__start__after = 0,
_pos__end__before = 0,
_pos__end__after = 0
;
// fast return
// ===========
switch (true)
{
case ((_tag_name == '#invalid')):
case (($R.parsingOptions._elements_ignore.indexOf('|'+_tag_name+'|') > -1)):
return;
case (_tag_name == '#text'):
_global__the_html += _node.nodeValue
.replace(/</gi, '<')
.replace(/>/gi, '>')
;
return;
}
// hidden
// ======
if ($R.parsingOptions._elements_visible.indexOf('|'+_tag_name+'|') > -1)
{
// included inline
// _node, _tag_name must be defined
// will return, if node is hidden
switch (true)
{
case (_node.offsetWidth > 0):
case (_node.offsetHeight > 0):
break;
default:
switch (true)
{
case (_node.offsetLeft > 0):
case (_node.offsetTop > 0):
break;
default:
// exclude inline DIVs -- which, stupidly, don't have a width/height
if ((_tag_name == 'div') && ((_node.style.display || $.css( _node, "display" )) == 'inline'))
{ break; }
// it's hidden; exit current scope
return;
}
break;
}
}
// clean -- before
// =====
// just a return will skip the whol element
// including children
// objects, embeds, iframes
// ========================
switch (_tag_name)
{
case ('object'):
case ('embed'):
case ('iframe'):
var
_src = (_tag_name == 'object' ? $(_node).find("param[name='movie']").attr('value') : $(_node).attr('src')),
_skip = ((_src > '') ? false : true)
;
if (_skip); else
{
// default skip
_skip = true;
// loop
for (var i=0, _i=$R.keepStuffFromDomain__video.length; i<_i; i++)
{ if (_src.indexOf($R.keepStuffFromDomain__video[i]) > -1) { _skip = false; break; } }
}
// skip?
if (_skip)
{ $R.debugOutline(_node, 'clean-before', 'object-embed-iframe'); return; }
break;
}
// skipped link
// ============
if (_tag_name == 'a' || _tag_name == 'li')
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_explored._is__link_skip):
case (((_explored._count__images_small + _explored._count__images_skip) > 0) && (_explored._length__plain_text < 65)):
$R.debugOutline(_node, 'clean-before', 'skip-link');
return;
}
}
// link density
// ============
if ($R.parsingOptions._elements_link_density.indexOf('|'+_tag_name+'|') > -1)
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_explored._length__plain_text > (65 * 3 * 2)):
case ($R.language == 'cjk' && (_explored._length__plain_text > (65 * 3 * 1))):
case (!(_explored._count__links > 1)):
case (_global__exploreNodeToBuildHTMLFor && (_explored._length__plain_text / _global__exploreNodeToBuildHTMLFor._length__plain_text) > 0.5):
case (_global__exploreNodeToBuildHTMLFor && (_explored._count__plain_words / _global__exploreNodeToBuildHTMLFor._count__plain_words) > 0.5):
case ((_explored._length__plain_text == 0) && (_explored._count__links == 1) && (_explored._length__links_text < 65)):
case ((_explored._length__plain_text < 25) && ((_explored._count__images_large + _explored._count__images_medium) > 0)):
break;
case ((_explored._length__links_text / _explored._length__all_text) < 0.5):
if (_explored._count__links > 0); else { break; }
if (_explored._count__links_skip > 0); else { break; }
if (((_explored._count__links_skip / _explored._count__links) > 0.25) && (_explored._length__links_text / _explored._length__all_text) < 0.05) { break; }
default:
$R.debugOutline(_node, 'clean-before', 'link-density');
return;
}
}
// floating
// ========
if ($R.parsingOptions._elements_floating.indexOf('|'+_tag_name+'|') > -1)
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_explored._length__plain_text > (65 * 3 * 2)):
case ($R.language == 'cjk' && (_explored._length__plain_text > (65 * 3 * 1))):
case (_global__exploreNodeToBuildHTMLFor && (_explored._length__plain_text / _global__exploreNodeToBuildHTMLFor._length__plain_text) > 0.25):
case (_global__exploreNodeToBuildHTMLFor && (_explored._count__plain_words / _global__exploreNodeToBuildHTMLFor._count__plain_words) > 0.25):
case ((_explored._length__plain_text < 25) && (_explored._length__links_text < 25) && ((_explored._count__images_large + _explored._count__images_medium) > 0)):
case (_node.getElementsByTagName && (_explored._length__plain_text < (65 * 3 * 1)) && ((_node.getElementsByTagName('h1').length + _node.getElementsByTagName('h2').length + _node.getElementsByTagName('h3').length + _node.getElementsByTagName('h4').length) > 0)):
break;
default:
var _float = $(_node).css('float');
if (_float == 'left' || _float == 'right'); else { break; }
if ((_explored._length__links_text == 0) && ((_explored._count__images_large + _explored._count__images_medium) > 0)) { break; }
$R.debugOutline(_node, 'clean-before', 'floating');
return;
}
}
// above target
// ============
if (_custom_mode == 'above-the-target')
{
// is ignored?
if ($R.parsingOptions._elements_above_target_ignore.indexOf('|'+_tag_name+'|') > -1)
{ $R.debugOutline(_node, 'clean-before', 'above-target'); return; }
// is image?
if (_tag_name == 'img')
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
if (_explored._is__image_large); else
{ $R.debugOutline(_node, 'clean-before', 'above-target'); return; }
}
// has too many links?
//if (_node.getElementsByTagName && _node.getElementsByTagName('a').length > 5)
// { $R.debugOutline(_node, 'clean-before', 'above-target'); return; }
}
// headers that are images
// =======================
if (_tag_name.match(/^h(1|2|3|4|5|6)$/gi))
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case ((_explored._length__plain_text < 10) && ((_explored._count__images_small + _explored._count__images_medium + _explored._count__images_large + _explored._count__images_skip) > 0)):
$R.debugOutline(_node, 'clean-before', 'skip-heading');
return;
}
}
// start tag
// =========
if ($R.parsingOptions._elements_ignore_tag.indexOf('|'+_tag_name+'|') > -1); else
{
/* mark */ _pos__start__before = _global__the_html.length;
/* add */ _global__the_html += '<'+_tag_name;
// attributes
// ==========
// allowed attributes
// ==================
if (_tag_name in $R.parsingOptions._elements_keep_attributes)
{
for (var i=0, _i=$R.parsingOptions._elements_keep_attributes[_tag_name].length; i<_i; i++)
{
var
_attribute_name = $R.parsingOptions._elements_keep_attributes[_tag_name][i],
_attribute_value = _node.getAttribute(_attribute_name)
;
// if present
if (_attribute_value > '')
{ _global__the_html += ' '+_attribute_name+'="'+(_attribute_value)+'"'; }
}
}
// keep ID for all elements
// ========================
var _id_attribute = _node.getAttribute('id');
if (_id_attribute > '')
{ _global__the_html += ' id="'+_id_attribute+'"'; }
// links target NEW
// ================
if (_tag_name == 'a')
{ _global__the_html += ' target="_blank"'; }
// close start
// ===========
if ($R.parsingOptions._elements_self_closing.indexOf('|'+_tag_name+'|') > -1) { _global__the_html += ' />'; }
else { _global__the_html += '>';}
/* mark */ _pos__start__after = _global__the_html.length;
}
// child nodes
// ===========
if ($R.parsingOptions._elements_self_closing.indexOf('|'+_tag_name+'|') > -1); else
{
for (var i=0, _i=_node.childNodes.length; i<_i; i++)
{ _recursive(_node.childNodes[i]); }
}
// end tag
// =======
switch (true)
{
case (($R.parsingOptions._elements_ignore_tag.indexOf('|'+_tag_name+'|') > -1)):
return;
case (($R.parsingOptions._elements_self_closing.indexOf('|'+_tag_name+'|') > -1)):
/* mark */ _pos__end__before = _global__the_html.length;
/* mark */ _pos__end__after = _global__the_html.length;
break;
default:
/* mark */ _pos__end__before = _global__the_html.length;
/* end */ _global__the_html += '</'+_tag_name+'>';
/* mark */ _pos__end__after = _global__the_html.length;
break;
}
// clean -- after
// =====
// we need to actually cut things out of
// "_global__the_html", for stuff to not be there
// largeObject classes
// ===================
if (_tag_name == 'iframe' || _tag_name == 'embed' || _tag_name == 'object')
{
_global__the_html = ''
+ _global__the_html.substr(0, _pos__start__before)
+ '<div class="readableLargeObjectContainer">
'
+ _global__the_html.substr(_pos__start__before, (_pos__end__after - _pos__start__before))
+ '</div>
'
;
return;
}
// add image classes
// =================
if (_tag_name == 'img')
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_explored._is__image_skip):
$R.debugOutline(_node, 'clean-after', 'skip-img');
_global__the_html = _global__the_html.substr(0, _pos__start__before);
return;
case (_explored._is__image_large):
// add float class -- for images too narrow/tall
// remove width/height -- only for large images
// http://www.wired.com/threatlevel/2011/05/gps-gallery/?pid=89&viewall=true
// http://david-smith.org/blog/2012/03/10/ios-5-dot-1-upgrade-stats/index.html
// http://www.turntablekitchen.com/2012/04/dutch-baby-with-caramelized-vanilla-bean-pears-moving-through-the-decades/
_global__the_html = ''
+ _global__the_html.substr(0, _pos__start__before)
+ '<div class="readableLargeImageContainer'
+ (($(_node).width() <= 250) && ($(_node).height() >
= 250) ? ' float' : '')
+ '">'
+ _global__the_html.substr(_pos__start__before, (_pos__end__after - _pos__start__before)).replace(/width="([^=]+?)"/gi, '').replace(/height="([^=]+?)"/gi, '')
+ '</div>
'
;
return;
}
}
// large images in links
// =====================
if (_tag_name == 'a')
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_explored._count__images_large == 1):
_global__the_html = ''
+ _global__the_html.substr(0, _pos__start__after-1)
+ ' class="readableLinkWithLargeImage">'
+ _global__the_html.substr(_pos__start__after, (_pos__end__before - _pos__start__after))
+ '</a>'
;
return;
case (_explored._count__images_medium == 1):
_global__the_html = ''
+ _global__the_html.substr(0, _pos__start__after-1)
+ ' class="readableLinkWithMediumImage">'
+ _global__the_html.substr(_pos__start__after, (_pos__end__before - _pos__start__after))
+ '</a>'
;
return;
}
}
// too much content
// ================
if ($R.parsingOptions._elements_too_much_content.indexOf('|'+_tag_name+'|') > -1)
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
switch (true)
{
case (_tag_name == 'h1' && (_explored._length__all_text > (65 * 2))):
case (_tag_name == 'h2' && (_explored._length__all_text > (65 * 2 * 3))):
case ((_tag_name.match(/^h(3|4|5|6)$/) != null) && (_explored._length__all_text > (65 * 2 * 5))):
case ((_tag_name.match(/^(b|i|em|strong)$/) != null) && (_explored._length__all_text > (65 * 5 * 5))):
$R.debugOutline(_node, 'clean-after', 'too-much-content');
_global__the_html = ''
+ _global__the_html.substr(0, _pos__start__before)
+ _global__the_html.substr(_pos__start__after, (_pos__end__before - _pos__start__after))
;
return;
}
}
// empty elements
// ==============
switch (true)
{
case (($R.parsingOptions._elements_self_closing.indexOf('|'+_tag_name+'|') > -1)):
case (($R.parsingOptions._elements_ignore_tag.indexOf('|'+_tag_name+'|') > -1)):
case (_tag_name == 'td'):
break;
default:
var _contents = _global__the_html.substr(_pos__start__after, (_pos__end__before - _pos__start__after));
_contents = _contents.replace(/(<br \/>)/gi, '');
_contents = _contents.replace(/(<hr \/>
)/gi, '');
// for rows, clear empty cells
if (_tag_name == 'tr')
{
_contents = _contents.replace(/<td[^>]*?>/gi, '');
_contents = _contents.replace(/<\/td>/gi, '');
}
// for tables, clear empty rows
if (_tag_name == 'table')
{
_contents = _contents.replace(/<tr[^>]*?>/gi, '');
_contents = _contents.replace(/<\/tr>/gi, '');
}
var _contentsLength = $R.measureText__getTextLength(_contents);
switch (true)
{
case (_contentsLength == 0 && _tag_name == 'p'):
_global__the_html = _global__the_html.substr(0, _pos__start__before) + '<br /><br />';
return;
case (_contentsLength == 0):
case ((_contentsLength < 5) && ($R.parsingOptions._elements_visible.indexOf('|'+_tag_name+'|') > -1)):
$R.debugOutline(_node, 'clean-after', 'blank');
_global__the_html = _global__the_html.substr(0, _pos__start__before);
return;
}
break;
}
// too much missing
// ================
if ($R.parsingOptions._elements_link_density.indexOf('|'+_tag_name+'|') > -1)
{
_explored = (_explored || $R.getContent__exploreNodeAndGetStuff(_node, true));
var
_contents = _global__the_html
.substr(_pos__start__after, (_pos__end__before - _pos__start__after))
.replace(/(<([^>]+)>)/gi, ''),
_contentsLength = $R.measureText__getTextLength(_contents),
_initialLength = 0
+ _explored._length__all_text
+ (_explored._count__images_small * 10)
+ (_explored._count__images_skip * 10)
+ (_node.getElementsByTagName('iframe').length * 10)
+ (_node.getElementsByTagName('object').length * 10)
+ (_node.getElementsByTagName('embed').length * 10)
+ (_node.getElementsByTagName('button').length * 10)
+ (_node.getElementsByTagName('input').length * 10)
+ (_node.getElementsByTagName('select').length * 10)
+ (_node.getElementsByTagName('textarea').length * 10)
;
// too much missing
switch (true)
{
case (!(_contentsLength > 0)):
case (!(_initialLength > 0)):
case (!((_contentsLength / _initialLength) < 0.5)):
case (!(($R.language == 'cjk') && (_contentsLength / _initialLength) < 0.1)):
case ((_global__exploreNodeToBuildHTMLFor && ((_explored._length__plain_text / _global__exploreNodeToBuildHTMLFor._length__plain_text) > 0.25))):
case (($R.language == 'cjk') && (_global__exploreNodeToBuildHTMLFor && ((_explored._length__plain_text / _global__exploreNodeToBuildHTMLFor._length__plain_text) > 0.1))):
break;
default:
$R.debugOutline(_node, 'clean-after', 'missing-density');
_global__the_html = _global__the_html.substr(0, _pos__start__before);
return;
}
}
// return
return;
};
// actually do it
_recursive(_nodeToBuildHTMLFor);
// return html
return _global__the_html;
};
// article title marker
// ====================
$R.articleTitleMarker__start = '<div id="articleHeader">
<h1>
';
$R.articleTitleMarker__end = '</h1>
</div>
';
// article title check function
// ============================
$R.getContent__find__hasIsolatedTitleInHTML = function (_html)
{
return (_html.substr(0, $R.articleTitleMarker__start.length) == $R.articleTitleMarker__start);
};
// article title get function
// ============================
$R.getContent__find__getIsolatedTitleInHTML = function (_html)
{
// is it there?
if ($R.getContent__find__hasIsolatedTitleInHTML(_html)); else { return ''; }
// regex
var
_getTitleRegex = new RegExp($R.articleTitleMarker__start + '(.*?)' + $R.articleTitleMarker__end, 'i'),
_getTitleMatch = _html.match(_getTitleRegex)
;
// match?
if (_getTitleMatch); else { return ''; }
// return
return _getTitleMatch[1];
};
// find title in arbitrary html
// ============================
$R.getContent__find__isolateTitleInHTML = function (_html, _document_title)
{
// can't just use (h1|h2|h3|etc) -- we want to try them in a certain order
// =============================
var
_heading_pregs = [
/<(h1)[^>]*?>([\s\S]+?)<\/\1>/gi,
/<(h2)[^>]*?>([\s\S]+?)<\/\1>/gi,
/<(h3|h4|h5|h6)[^>]*?>([\s\S]+?)<\/\1>/gi
],
_secondary_headings = '|h2|h3|h4|h5|h6|',
_search_document_title = ' ' + _document_title.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ') + ' '
;
// loop pregs
// ==========
for (var i=0, _i=_heading_pregs.length; i<_i; i++)
{
// exec
var _match = _heading_pregs[i].exec(_html);
// return?
switch (true)
{
case (!(_match)):
case (!(_heading_pregs[i].lastIndex > -1)):
// will continue loop
break;
default:
// measurements
var
_heading_end_pos = _heading_pregs[i].lastIndex,
_heading_start_pos = (_heading_end_pos - _match[0].length),
_heading_type = _match[1],
_heading_text = _match[2].replace(/<\s*br[^>]*>/gi, '').replace(/[\n\r]+/gi, ''),
_heading_text_plain = _heading_text.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ');
_heading_length = $R.measureText__getTextLength(_heading_text_plain),
_heading_words = [],
_to_heading_text = _html.substr(0, _heading_start_pos),
_to_heading_length = $R.measureText__getTextLength(_to_heading_text.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' '))
;
// return?
switch (true)
{
case (!(_heading_length > 5)):
case (!(_heading_length < (65 * 3))):
case (!(_to_heading_length < (65 * 3 * 2))):
// will continue for loop
break;
case ((_secondary_headings.indexOf('|' + _heading_type + '|') > -1)):
// words in this heading
_heading_words = _heading_text_plain.split(' ');
// count words present in title
for (var j=0, _j=_heading_words.length, _matched_words=''; j<_j; j++) {
if (_search_document_title.indexOf(' ' + _heading_words[j] + ' ') > -1) {
_matched_words += _heading_words[j] + ' ';
}
}
// break continues for loop
// nothing goes to switch's default
// ================================
// no break?
var _no_break = false;
switch (true)
{
// if it's big enough, and it's a substring of the title, it's good
case ((_heading_length > 20) && (_search_document_title.indexOf(_heading_text_plain) > -1)):
// if it's slightly smaler, but is exactly at the begging or the end
case ((_heading_length > 10) && ((_search_document_title.indexOf(_heading_text_plain) == 1) || (_search_document_title.indexOf(_heading_text_plain) == (_search_document_title.length - 1 - _heading_text_plain.length)))):
_no_break = true;
break;
}
// break?
var _break = false;
switch (true)
{
// no break?
case (_no_break):
break;
// heading too long? -- if not h2
case ((_heading_length > ((_search_document_title.length - 2) * 2)) && (_heading_type != 'h2')):
// heading long enough?
case ((_heading_length < Math.ceil((_search_document_title.length - 2) * 0.50))):
// enough words matched?
case ((_heading_length < 25) && (_matched_words.length < Math.ceil(_heading_length * 0.75))):
case ((_heading_length < 50) && (_matched_words.length < Math.ceil(_heading_length * 0.65))):
case ((_matched_words.length < Math.ceil(_heading_length * 0.55))):
_break = true;
break;
}
// break?
if (_break) { break; }
default:
// this is the title -- do isolation; return
// =================
return ''
+ $R.articleTitleMarker__start
+ _heading_text
+ $R.articleTitleMarker__end
+ _html.substr(_heading_end_pos)
;
}
break;
}
}
// return unmodified
return _html;
};
$R.getContent__find = function ()
{
// get content
// ===========
var
_found = $R.getContent__findInPage($R.win),
_targetNode = _found._targetCandidate.__node,
_$targetNode = $(_targetNode),
_aboveNodes = []
;
// RTL
// ===
switch (true)
{
case (_$targetNode.attr('dir') == 'rtl'):
case (_$targetNode.css('direction') == 'rtl'):
$R.makeRTL();
break;
}
// get html
// ========
var
_foundHTML = _found._html,
_firstFragmentBefore = $R.getContent__nextPage__getFirstFragment(_foundHTML),
_documentTitle = ($R.document.title > '' ? $R.document.title : '')
;
// get title
// =========
// has title already?
_foundHTML = $R.getContent__find__isolateTitleInHTML(_foundHTML, _documentTitle);
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'target');
// get html above?
if ($R.articleTitle > ''); else
{
// get html above target?
// ======================
// global vars:
// _found
// _foundHTML
// _documentTitle
// _aboveNodes
var
_prevNode = _found._targetCandidate.__node,
_prevHTML = '',
_aboveHTML = '',
_differentTargets = (_found._firstCandidate.__node != _found._targetCandidate.__node)
;
(function ()
{
while (true)
{
// the end?
switch (true)
{
case (_prevNode.tagName && (_prevNode.tagName.toLowerCase() == 'body')):
case (_differentTargets && (_prevNode == _found._firstCandidate.__node)):
// enough is enough
return;
}
// up or sideways?
if (_prevNode.previousSibling); else
{
_prevNode = _prevNode.parentNode;
continue;
}
// previous
_prevNode = _prevNode.previousSibling;
// outline -- element might be re-outlined, when buildHTML is invoked
if ($R.debug) { $R.debugOutline(_prevNode, 'target', 'add-above'); }
// get html; add
_prevHTML = $R.getContent__buildHTMLForNode(_prevNode, 'above-the-target');
_aboveHTML = _prevHTML + _aboveHTML;
_aboveNodes.unshift(_prevNode);
// isolate title
_aboveHTML = $R.getContent__find__isolateTitleInHTML(_aboveHTML, _documentTitle);
// finished?
switch (true)
{
case ($R.measureText__getTextLength(_aboveHTML.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ')) > (65 * 3 * 3)):
case ($R.getContent__find__hasIsolatedTitleInHTML(_aboveHTML)):
return;
}
}
})();
// is what we found any good?
// ==========================
switch (true)
{
case ($R.getContent__find__hasIsolatedTitleInHTML(_aboveHTML)):
case (_differentTargets && (_aboveHTML.split('<a ').length < 3) && ($R.measureText__getTextLength(_aboveHTML.replace(/<[^>]+?>/gi, '').replace(/\s+/gi, ' ')) < (65 * 3))):
_foundHTML = _aboveHTML + _foundHTML;
break;
default:
_aboveHTML = '';
_aboveNodes = [];
break;
}
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'above_HTML');
// get document title?
if ($R.articleTitle > ''); else
{
// if all else failed, get document title
// ======================================
// global vars:
// _foundHTML
// _documentTitle
(function ()
{
// return?
// =======
if (_documentTitle > ''); else { return; }
// vars
var
_doc_title_parts = [],
_doc_title_pregs =
[
/( [-][-] |( [-] )|( [>][>] )|( [<][<] )|( [|] )|( [\/] ))/i,
/(([:] ))/i
]
;
// loop through pregs
// ==================
for (var i=0, _i=_doc_title_pregs.length; i<_i; i++)
{
// split
_doc_title_parts = _documentTitle.split(_doc_title_pregs[i]);
// break if we managed a split
if (_doc_title_parts.length > 1) { break; }
}
// sort title parts -- longer goes higher up -- i.e. towards 0
// ================
_doc_title_parts.sort(function (a, b)
{
switch (true)
{
case (a.length > b.length): return -1;
case (a.length < b.length): return 1;
default: return 0;
}
});
// set title -- first part, if more than one word; otherwise, whole
// =========
_foundHTML = ''
+ $R.articleTitleMarker__start
+ (_doc_title_parts[0].split(/\s+/i).length > 1 ? _doc_title_parts[0] : _documentTitle)
+ $R.articleTitleMarker__end
+ _foundHTML
;
})();
$R.articleTitle = $R.getContent__find__getIsolatedTitleInHTML(_foundHTML);
$R.debugPrint('TitleSource', 'document_title');
}
}
// display
// =======
$R.$pages.html('');
$R.displayPageHTML(_foundHTML, 1, $R.win.location.href);
// remember
// ========
$R.debugRemember['theTarget'] = _found._targetCandidate.__node;
$R.debugRemember['firstCandidate'] = _found._firstCandidate.__node;
// next
// ====
$R.nextPage__firstFragment__firstPage = _firstFragmentBefore;
$R.nextPage__firstFragment__lastPage = $R.getContent__nextPage__getFirstFragment(_foundHTML);;
$R.nextPage__loadedPages = [$R.win.location.href];
$R.getContent__nextPage__find($R.win, _found._links);
// return
return true;
};
$R.getContent__findInPage = function (_pageWindow)
{
// calculations
// ============
var
_firstCandidate = false,
_secondCandidate = false,
_targetCandidate = false
;
$R.debugTimerStart('ExploreAndGetStuff');
var _stuff = $R.getContent__exploreNodeAndGetStuff(_pageWindow.document.body);
$R.debugPrint('ExploreAndGetStuff', $R.debugTimerEnd()+'ms');
$R.debugTimerStart('ProcessFirst');
var _processedCandidates = $R.getContent__processCandidates(_stuff._candidates);
_firstCandidate = _processedCandidates[0];
_targetCandidate = _firstCandidate;
$R.debugPrint('ProcessFirst', $R.debugTimerEnd()+'ms');
// debug
if ($R.debug)
{
// debug first candidates
$R.log('First 5 Main Candidates:');
for (var x in _processedCandidates)
{
if (x == 5) { break; }
$R.log(_processedCandidates[x], _processedCandidates[x].__node);
}
// highlight first
$R.debugOutline(_firstCandidate.__node, 'target', 'first');
}
// in case we stop
$R.debugPrint('Target', 'first');
// do second?
switch (true)
{
case (!(_firstCandidate._count__containers > 0)):
case (!(_firstCandidate._count__candidates > 0)):
case (!(_firstCandidate._count__pieces > 0)):
case (!(_firstCandidate._count__containers > 25)):
break;
default:
$R.debugTimerStart('ProcessSecond');
var _processedCandidatesSecond = $R.getContent__processCandidatesSecond(_processedCandidates);
_secondCandidate = _processedCandidatesSecond[0];
$R.debugPrint('ProcessSecond', $R.debugTimerEnd()+'ms');
// they're the same
if (_firstCandidate.__node == _secondCandidate.__node) { break; }
// debug
if ($R.debug)
{
// log second candidates
$R.log('First 5 Second Candidates:');
for (var x in _processedCandidatesSecond)
{
if (x == 5) { break; }
$R.log(_processedCandidatesSecond[x], _processedCandidatesSecond[x].__node);
}
// highlight second
$R.debugOutline(_secondCandidate.__node, 'target', 'second');
}
// compute again
// =============
_firstCandidate['__points_history_final'] = $R.getContent__computePointsForCandidateThird(_firstCandidate, _firstCandidate);
_firstCandidate['__points_final'] = _firstCandidate.__points_history_final[0];
_secondCandidate['__points_history_final'] = $R.getContent__computePointsForCandidateThird(_secondCandidate, _firstCandidate);
_secondCandidate['__points_final'] = _secondCandidate.__points_history_final[0];
// log results
// ===========
if ($R.debug)
{
$R.log('The 2 Candidates:');
$R.log(_firstCandidate);
$R.log(_secondCandidate);
}
// are we selecting _second?
// =========================
switch (true)
{
case ((_secondCandidate.__candidate_details._count__lines_of_65_characters < 20) && (_secondCandidate.__points_final / _firstCandidate.__points_final) > 1):
case ((_secondCandidate.__candidate_details._count__lines_of_65_characters > 20) && (_secondCandidate.__points_final / _firstCandidate.__points_final) > 0.9):
case ((_secondCandidate.__candidate_details._count__lines_of_65_characters > 50) && (_secondCandidate.__points_final / _firstCandidate.__points_final) > 0.75):
_targetCandidate = _secondCandidate;
$R.debugPrint('Target', 'second');
break;
}
// print points
// ============
if ($R.debug)
{
$R.debugPrint('PointsFirst', _firstCandidate['__points_history_final'][0].toFixed(2));
$R.debugPrint('PointsSecond', _secondCandidate['__points_history_final'][0].toFixed(2));
}
break;
}
// highlight target
// ================
if ($R.debug)
{
$(_targetCandidate.__node).css({
'box-shadow':
'inset 0px 0px 50px rgba(255, 255, 0, 0.95), 0px 0px 50px rgba(255, 255, 0, 0.95)'
});
}
// get html
// ========
$R.debugTimerStart('BuildHTML');
var _html = $R.getContent__buildHTMLForNode(_targetCandidate.__node, 'the-target');
_html = _html.substr((_html.indexOf('>')+1))
_html = _html.substr(0, _html.lastIndexOf('<'));
$R.debugPrint('BuildHTML', $R.debugTimerEnd()+'ms');
$R.debugTimerStart('BuildHTMLPregs');
_html = _html.replace(/<(blockquote|div|p|td|li)([^>]*)>(\s*<br \/>)+/gi, '<$1$2>');
_html = _html.replace(/(<br \/>\s*)+<\/(blockquote|div|p|td|li)>/gi, '</$2>');
_html = _html.replace(/(<br \/>\s*)+<(blockquote|div|h\d|ol|p|table|ul|li)([^>]*)>/gi, '<$2$3>');
_html = _html.replace(/<\/(blockquote|div|h\d|ol|p|table|ul|li)>(\s*<br \/>)+/gi, '</$1>');
_html = _html.replace(/(<hr \/>
\s*<hr \/>
\s*)+/gi, '<hr />
');
_html = _html.replace(/(<br \/>\s*<br \/>\s*)+/gi, '<br /><br />');
$R.debugPrint('BuildHTMLPregs', $R.debugTimerEnd()+'ms');
// return
// ======
return {
'_html': _html,
'_links': _stuff._links,
'_targetCandidate': _targetCandidate,
'_firstCandidate': _firstCandidate
};
};
// get first page fragment
// =======================
$R.getContent__nextPage__getFirstFragment = function (_html)
{
// remove all tags
_html = _html.replace(/<[^>]+?>/gi, '');
// normalize spaces
_html = _html.replace(/\s+/gi, ' ');
// return first 1000 characters
return _html.substr(0, 2000);
};
// get link parts
// ==============
// substr starting with the first slash after //
$R.getURLPath = function (_url)
{
return _url.substr(_url.indexOf('/', (_url.indexOf('//') + 2)));
};
// substr until the first slash after //
$R.getURLDomain = function (_url)
{
return _url.substr(0, _url.indexOf('/', (_url.indexOf('//') + 2)))
};
// find
// ====
$R.getContent__nextPage__find = function (_currentPageWindow, _linksInCurrentPage)
{
// page id
var _pageNr = ($R.nextPage__loadedPages.length + 1);
// get
// ===
var _possible = [];
if (_possible.length > 0); else { _possible = $R.getContent__nextPage__find__possible(_currentPageWindow, _linksInCurrentPage, 0.5); }
//if (_possible.length > 0); else { _possible = $R.getContent__nextPage__find__possible(_currentPageWindow, _linksInCurrentPage, 0.50); }
// none
if (_possible.length > 0); else
{ if ($R.debug) { $R.log('no next link found'); } return; }
if ($R.debug) { $R.log('possible next', _possible); }
// the one
// =======
var _nextLink = false;
// next keyword?
// =============
(function ()
{
if (_nextLink) { return; }
for (var i=0, _i=_possible.length; i<_i; i++)
{
for (var j=0, _j=$R.nextPage__captionKeywords.length; j<_j; j++)
{
if (_possible[i]._caption.indexOf($R.nextPage__captionKeywords[j]) > -1)
{
// length
// ======
if (_possible[i]._caption.length > $R.nextPage__captionKeywords[j].length * 2)
{ continue; }
// not keywords
// ============
for (var z=0, _z=$R.nextPage__captionKeywords__not.length; z<_z; z++)
{
if (_possible[i]._caption.indexOf($R.nextPage__captionKeywords__not[z]) > -1)
{ _nextLink = false; return; }
}
// got it
// ======
_nextLink = _possible[i];
return;
}
}
}
})();
// caption matched page number
// ===========================
(function ()
{
if (_nextLink) { return; }
for (var i=0, _i=_possible.length; i<_i; i++)
{
if (_possible[i]._caption == (''+_pageNr))
{ _nextLink = _possible[i]; return; }
}
})();
// next keyword in title
// =====================
(function ()
{
if (_nextLink) { return; }
for (var i=0, _i=_possible.length; i<_i; i++)
{
// sanity
if (_possible[i]._title > ''); else { continue; }
if ($R.measureText__getTextLength(_possible[i]._caption) <= 2); else { continue; }
for (var j=0, _j=$R.nextPage__captionKeywords.length; j<_j; j++)
{
if (_possible[i]._title.indexOf($R.nextPage__captionKeywords[j]) > -1)
{
// length
// ======
if (_possible[i]._title.length > $R.nextPage__captionKeywords[j].length * 2)
{ continue; }
// not keywords
// ============
for (var z=0, _z=$R.nextPage__captionKeywords__not.length; z<_z; z++)
{
if (_possible[i]._title.indexOf($R.nextPage__captionKeywords__not[z]) > -1)
{ _nextLink = false; return; }
}
// got it
// ======
_nextLink = _possible[i];
return;
}
}
}
})();
// return?
// =======
if (_nextLink); else { return; }
// mark
// ====
$R.debugPrint('NextPage', 'true');
if ($R.debug)
{
$R.debugOutline(_nextLink._node, 'target', 'next-page');
$R.log('NextPage Link', _nextLink, _nextLink._node);
}
// process page
// ============
$R.getContent__nextPage__loadToFrame(_pageNr, _nextLink._href);
$R.nextPage__loadedPages.push(_nextLink._href);
};
// find with similarity
// ====================
$R.getContent__nextPage__find__possible = function (_currentPageWindow, _linksInCurrentPage, _distanceFactor)
{
var
_mainPageHref = $R.win.location.href,
_mainPageDomain = $R.getURLDomain(_mainPageHref),
_mainPagePath = $R.getURLPath(_mainPageHref)
;
var _links = $.map
(
_linksInCurrentPage,
function (_element, _index)
{
var
_href = _element.__node.href,
_path = $R.getURLPath(_href),
_title = (_element.__node.title > '' ? _element.__node.title.toLowerCase() : ''),
_caption = _element.__node.innerHTML.replace(/<[^>]+?>/gi, '').replace(/\&[^\&\s;]{1,10};/gi, '').replace(/\s+/gi, ' ').replace(/^ /, '').replace(/ $/, '').toLowerCase(),
_distance = $R.levenshteinDistance(_mainPagePath, _path)
;
var _caption2 = '';
for (var i=0, _i=_caption.length, _code=0; i<_i; i++)
{
_code = _caption.charCodeAt(i);
_caption2 += (_code > 127 ? ('&#'+_code+';') : _caption.charAt(i));
}
_caption = _caption2;
switch (true)
{
case (!(_href > '')):
case (_mainPageHref.length > _href.length):
case (_mainPageDomain != $R.getURLDomain(_href)):
case (_href.substr(_mainPageHref.length).substr(0, 1) == '#'):
case (_distance > Math.ceil(_distanceFactor * _path.length)):
return null;
default:
// skip if already loaded as next page
for (var i=0, _i=$R.nextPage__loadedPages.length; i<_i; i++)
{ if ($R.nextPage__loadedPages[i] == _href) { return null; } }
// return
return {
'_node': _element.__node,
'_href': _href,
'_title': _title,
'_caption': _caption,
'_distance': _distance
};
}
}
);
// sort -- the less points, the closer to position 0
// ====
_links.sort(function (a, b)
{
switch (true)
{
case (a._distance < b._distance): return -1;
case (a._distance > b._distance): return 1;
default: return 0;
}
});
// return
return _links;
};
// load to frame
// =============
$R.getContent__nextPage__loadToFrame = function (_pageNr, _nextPageURL)
{
// do ajax
// =======
$.ajax
({
'url' : _nextPageURL,
'type' : 'GET',
'dataType' : 'html',
'async' : true,
'timeout': (10 * 1000),
//'headers': { 'Referrer': _nextPageURL },
'success' : function (_response, _textStatus, _xhr) { $R.getContent__nextPage__ajaxComplete(_pageNr, _response, _textStatus, _xhr); },
'error' : function (_xhr, _textStatus, _error) { $R.getContent__nextPage__ajaxError(_pageNr, _xhr, _textStatus, _error); }
});
};
// ajax calbacks
// =============
$R.getContent__nextPage__ajaxError = function (_pageNr, _xhr, _textStatus, _error)
{
};
$R.getContent__nextPage__ajaxComplete = function (_pageNr, _response, _textStatus, _xhr)
{
// valid?
// ======
if (_response > ''); else { return; }
// script
// ======
var _script = ''
+ '<script type="text/javascript">'
+ ' function __this_page_loaded()'
+ ' {'
+ ' window.setTimeout('
+ ' function () {'
+ ($R.component ? 'window.parent.' : 'window.parent.parent.')
+ '$readable.getContent__nextPage__loadedInFrame("'+_pageNr+'", window); }, '
+ ' 250'
+ ' );'
+ ' } '
+ ' if (document.readyState); else { __this_page_loaded(); } '
+ ' function __this_page_loaded_ready(delayedNrTimes)'
+ ' {'
+ ' if (document.readyState != "complete" && delayedNrTimes < 30)'
+ ' { setTimeout(function () { __this_page_loaded_ready(delayedNrTimes+1); }, 100); return; }'
+ ' __this_page_loaded();'
+ ' }'
+ ' __this_page_loaded_ready(0);'
+ '</script><script>]*?>([\s\S]*?)<\/script>/gi, '');
_html = _html.replace(/<script[^>]*?\/>/gi, '');
_html = _html.replace(/<noscript[^>]*?>([\s\S]*?)<\/noscript>/gi, '');
_html = _html.replace(/<onload="*?" id="nextPageFrame__'+_pageNr+'" ?="" +="" frameborder="0" scrolling="no" ?<iframe?="" $R.$nextPages.append(??="" frame="" append="" body?);="" _script+?<="" _html="_html.replace(/<\/body/i," handler="" load="" add="" ??);="" gi,="">'
);
// write to frame
// ==============
var _doc = $('#nextPageFrame__'+_pageNr).contents().get(0);
_doc.open();
_doc.write(_html);
_doc.close();
};
// loaded in frame
// ===============
$R.getContent__nextPage__loadedInFrame = function (_pageNr, _pageWindow)
{
// find
// ====
var
_found = $R.getContent__findInPage(_pageWindow),
_foundHTML = _found._html,
_removeTitleRegex = new RegExp($R.articleTitleMarker__start + '(.*?)' + $R.articleTitleMarker__end, 'i')
;
// get first fragment
// ==================
var _firstFragment = $R.getContent__nextPage__getFirstFragment(_foundHTML);
// gets first 2000 characters
// diff set at 100 -- 0.05
switch (true)
{
case ($R.levenshteinDistance(_firstFragment, $R.nextPage__firstFragment__firstPage) < 100):
case ($R.levenshteinDistance(_firstFragment, $R.nextPage__firstFragment__lastPage) < 100):
// mark
$R.debugPrint('NextPage', 'false');
// mark again
if ($R.debug) { $('#debugOutput__value__NextPage').html('false'); }
// pop page
$R.nextPage__loadedPages.pop();
// break
return false;
default:
// add to first fragemnts
$R.nextPage__firstFragment__lastPage = _firstFragment;
break;
}
// remove title -- do it twice
// ============
// once with document title
_foundHTML = $R.getContent__find__isolateTitleInHTML(_foundHTML, ($R.document.title > '' ? $R.document.title : ''));
_foundHTML = _foundHTML.replace(_removeTitleRegex, '');
// once with article title
_foundHTML = $R.getContent__find__isolateTitleInHTML(_foundHTML, $R.articleTitle);
_foundHTML = _foundHTML.replace(_removeTitleRegex, '');
// display
// =======
$R.displayPageHTML(_foundHTML, _pageNr, _pageWindow.location.href);
// next
// ====
$R.getContent__nextPage__find(_pageWindow, _found._links);
};
// rewrites
// ========
// rewrite displayPageHTML -- for multi-page articles
// =======================
$R.displayPageHTML = function (_processedPageHTML, _pageNr, _pageURL)
{
// skip first
if (_pageNr > 1); else { return; }
// push to pages
$C._nextPages.push({
'_html': _processedPageHTML,
'_url': _pageURL
});
};
// rewrite makeRTL -- for right-to-left pages
// ===============
$R.makeRTL = function () { $R.rtl = true; };
$R.makeNotRTL = function () { $R.rtl = false; }
// set component object
// ====================
window.ClearlyComponent = $C;
window.$readable = $R;
}
<script type="text/javascript" defer="" charset="ANSI">/*
http://www.JSON.org/json2.js
2008-11-19
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or ' '),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the object holding the key.
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
*/
/*jslint evil: true */
/*global JSON */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (!this.JSON) {
JSON = {};
}
(function () {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ?
'"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' :
'"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' :
gap ? '[\n' + gap +
partial.join(',\n' + gap) + '\n' +
mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
k = rep[i];
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' :
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
})();
</script><script charset="ANSI" defer="" type="text/javascript">// HTML5 placeholder plugin version 1.01
// Copyright (c) 2010-The End of Time, Mike Taylor, http://miketaylr.com
// MIT Licensed: http://www.opensource.org/licenses/mit-license.php
//
// Enables cross-browser HTML5 placeholder for inputs, by first testing
// for a native implementation before building one.
//
//
// USAGE:
//$('input[placeholder]').placeholder();
// <input type="text" placeholder="username">
(function($){
//feature detection
var hasPlaceholder = 'placeholder' in document.createElement('input');
//sniffy sniff sniff -- just to give extra left padding for the older
//graphics for type=email and type=url
var isOldOpera = $.browser.opera && $.browser.version < 10.5;
$.fn.placeholder = function(options) {
//merge in passed in options, if any
var options = $.extend({}, $.fn.placeholder.defaults, options),
//cache the original 'left' value, for use by Opera later
o_left = options.placeholderCSS.left;
//first test for native placeholder support before continuing
//feature detection inspired by ye olde jquery 1.4 hawtness, with paul irish
return (hasPlaceholder) ? this : this.each(function() {
//local vars
var $this = $(this),
inputVal = $.trim($this.val()),
inputWidth = $this.width(),
inputHeight = $this.height(),
//grab the inputs id for the <label @for>, or make a new one from the Date
inputId = (this.id) ? this.id : 'placeholder' + (+new Date()),
placeholderText = options.placeholderText ? options.placeholderText : $this.attr('placeholder'),
placeholder = $('<label for=\"'+ inputId +'\">'+ placeholderText + '</label>');
//stuff in some calculated values into the placeholderCSS object
options.placeholderCSS['width'] = inputWidth;
options.placeholderCSS['height'] = inputHeight;
// adjust position of placeholder
options.placeholderCSS.left = (isOldOpera && (this.type == 'email' || this.type == 'url')) ?
'11%' : o_left;
placeholder.css(options.placeholderCSS);
//place the placeholder if the input is empty
$this.wrap(options.inputWrapper);
$this.attr('id', inputId).after(placeholder);
if(inputVal) {
$this.next().hide();
}
//hide placeholder on focus
$this.focus(function(){
$this.next().hide();
});
//show placeholder if the input is empty
$this.blur(function(){
if (!$.trim($this.val())){
$this.next().show();
};
});
});
};
//expose defaults
$.fn.placeholder.defaults = {
//you can pass in a custom wrapper
inputWrapper: '<div style="position:relative;">
</div>
',
placeholderText: null,
//more or less just emulating what webkit does here
//tweak to your hearts content
placeholderCSS: {
'font':'0.75em sans-serif',
'color':'#bababa',
'position': 'absolute',
'left':'5px',
'top':'3px',
'overflow': 'hidden'
}
};
})(jQuery);</script><script charset="ANSI" defer="" type="text/javascript">/**
* SelectionFinder provides mechanism for finding selection on the page via
* find(). It is able to traverse frames in order to find a selection. It will
* report whether there's a selection via hasSelection(). After doing find(),
* the selection is stored in the selection property, and the document property
* will contain the document in which the selection was found. Find method will
* only recurse documents if it was invoked as find(true), specifying to do
* recursive search. You can use reset() to undo find().
*/
Evernote.SelectionFinder = function SelectionFinder( doc ) {
this._document = doc;
};
Evernote.SelectionFinder.prototype._document = null;
Evernote.SelectionFinder.prototype._selection = null;
Evernote.SelectionFinder.prototype.hasSelection = function() {
Evernote.Logger.debug( "SelectionFinder.hasSelection()" );
var range = Evernote.Utils.fixIERangeObject(this.getRange());
return range && (range.startContainer != range.endContainer
|| (range.startContainer == range.endContainer && range.startOffset != range.endOffset));
};
Evernote.SelectionFinder.prototype.find = function( deep ) {
Evernote.Logger.debug( "SelectionFinder.find()" );
var result = this.findSelectionInDocument( this._document, deep );
this._document = result.document;
this._selection = result.selection;
};
Evernote.SelectionFinder.prototype.getRange = function() {
Evernote.Logger.debug( "SelectionFinder.getRange()" );
if ( !this._selection || this._selection.rangeCount == 0 ) {
return null;
}
if ( typeof this._selection.getRangeAt == 'function' ) {
return this._selection.getRangeAt( 0 );
}
if ( (window.Range && this._selection instanceof window.Range) || !this._selection.anchorNode ) {
return this._selection;
}
var range = this._document.createRange();
range.setStart( this._selection.anchorNode, this._selection.anchorOffset );
range.setEnd( this._selection.focusNode, this._selection.focusOffset );
return range;
};
Evernote.SelectionFinder.prototype.findSelectionInDocument = function( doc, deep ) {
try {
Evernote.Logger.debug( "SelectionFinder.findSelectionInDocument()" );
var sel = null;
var hasSelection = false;
var win = null;
try {
win = (doc.defaultView) ? doc.defaultView : window;
}
catch ( e ) {
win = window;
}
if ( typeof win.getSelection == 'function' ) {
sel = win.getSelection();
if ( sel && typeof sel.rangeCount != 'undefined' && sel.rangeCount > 0 ) {
Evernote.Logger.debug("Found selection by win.getSelection()");
hasSelection = true;
}
}
else if ( win.selection && typeof win.selection.createRange == 'function' ) {
sel = win.selection.createRange();
if ( win.selection.type == 'Text' && typeof sel.htmlText == 'string' && sel.htmlText.length > 0 ) {
Evernote.Logger.debug("Found selection by win.selection");
hasSelection = true;
}
}
else if ( doc.selection && (typeof doc.selection.createRange == 'function' || typeof doc.selection.createRange == 'object') ) {
sel = doc.selection.createRange();
if(doc.selection.type == "None")
sel = undefined;
if ( (doc.selection.type == 'Text') && (typeof sel.htmlText == 'string') && (sel.htmlText.length > 0) ) {
Evernote.Logger.debug("Found selection by doc.selection");
hasSelection = true;
}
}
if ( sel && !hasSelection && deep ) {
var nestedDocs = Evernote.Utils.getNestedDocuments( doc );
for ( var i = 0; i < nestedDocs.length; ++i ) {
if ( nestedDocs[ i ] ) {
var framedSel = this.findSelectionInDocument( nestedDocs[ i ], deep );
if ( framedSel && framedSel.selection && framedSel.selection.rangeCount > 0 ) {
return framedSel;
}
}
}
}
//if do not find any selection in document, try to find selection in HTMLTextArea|Input.
//Get Selection object for TextArea, and set selection as a Range object
if(doc.activeElement)
Evernote.Logger.debug( "Check selection in INPUT TEXT area (input, textarea), for active element :" + doc.activeElement.nodeName );
var activeEl = doc.activeElement;
if ( activeEl && ( (window.HTMLInputElement && (activeEl instanceof window.HTMLInputElement && activeEl.type == "text")) || ( window.HTMLTextAreaElement && (activeEl instanceof window.HTMLTextAreaElement)) ) ) {
if ( activeEl.selectionStart != activeEl.selectionEnd ) {
var range = doc.createRange();
var textNode = doc.createTextNode( activeEl.value );
range.setStart( textNode, activeEl.selectionStart );
range.setEnd( textNode, activeEl.selectionEnd );
sel = range;
}
}
return {
document : doc,
selection : sel
};
} catch(e) {
Evernote.Logger.error("Failed to find selection on the page due to error " + e);
//Do not throw exception here, it is better to not show error to user and allow to clip article or something else.
}
return {
document: doc,
selection: null
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.JSSerializer = {
_selectionFinder : new Evernote.SelectionFinder(window.document),
serializeAsync : function( element, fullPage, callback ) {
try {
var start = new Date().getTime();
var root = element || document.body.parentNode || document.body;
var serializer = new Evernote.NodeSerializer( window, new Evernote.ClipFullStylingStrategy() );
var parser = new Evernote.DomParser( window, null );
var resultFunc = function() {
var images = [];
var imageUrls = serializer.getImagesUrls();
for(var i = 0; i < imageUrls.length; i++) {
images.push(Evernote.Utils.makeAbsolutePath(serializer.getDocumentBase(), imageUrls[i]).replace(/\s/g, "%20"));
}
callback( {
content : serializer.getSerializedDom(),
imageUrls : images,
docBase : serializer.getDocumentBase()
});
};
parser.parseAsync( root, fullPage ? true: false, serializer, resultFunc);
var end = new Date().getTime();
Evernote.Logger.debug( "Clip.clipFullPage(): clipped body in " + (end - start) + " milliseconds" );
}
catch ( e ) {
Evernote.Logger.error( "JSSerializer.serialize() failed: error = " + e );
throw e;
}
},
serialize : function( element, fullPage ) {
try {
var start = new Date().getTime();
var root = element || document.body.parentNode || document.body;
var serializer = new Evernote.NodeSerializer( window, new Evernote.ClipFullStylingStrategy() );
var parser = new Evernote.DomParser( window, null );
parser.parse( root, fullPage ? true: false, serializer);
var end = new Date().getTime();
Evernote.Logger.debug( "Clip.clipFullPage(): clipped body in " + (end - start) + " milliseconds" );
var images = [];
var imageUrls = serializer.getImagesUrls();
for(var i = 0; i < imageUrls.length; i++) {
images.push(Evernote.Utils.makeAbsolutePath(serializer.getDocumentBase(), imageUrls[i]).replace(/\s/g, "%20"));
}
return {
content : serializer.getSerializedDom(),
imageUrls : images,
docBase : serializer.getDocumentBase()
}
}
catch ( e ) {
Evernote.Logger.error( "JSSerializer.serialize() failed: error = " + e );
throw e;
}
},
serializeSelectionAsync : function( range, callback ) {
try {
if( !range ) {
if ( !this.hasSelection() ) {
Evernote.Logger.warn( "JSSerializer.serializeSelection(): no selection to clip" );
callback();
return;
}
range = Evernote.Utils.fixIERangeObject(this._selectionFinder.getRange());
if ( !range ) {
Evernote.Logger.warn( "JSSerializer.serializeSelection(): no range in selection" );
callback();
return;
}
}
var start = new Date().getTime();
var ancestor = (this._styleStrategy && Evernote.Utils.Selection.getCommonAncestorContainer(range).nodeType == Evernote.Node.TEXT_NODE
&& Evernote.Utils.Selection.getCommonAncestorContainer(range).parentNode) ? Evernote.Utils.Selection.getCommonAncestorContainer(range).parentNode : Evernote.Utils.Selection.getCommonAncestorContainer(range);
while ( typeof Evernote.ClipRules.NON_ANCESTOR_NODES[ ancestor.nodeName.toUpperCase() ] != 'undefined' && ancestor.parentNode ) {
if ( ancestor.nodeName.toUpperCase() == "BODY" ) {
break;
}
ancestor = ancestor.parentNode;
}
var serializer = new Evernote.NodeSerializer( window, new Evernote.ClipFullStylingStrategy() );
var parser = new Evernote.DomParser(window, Evernote.Utils.fixIERangeObject(range));
var resultFunc = function() {
var images = [];
var imageUrls = serializer.getImagesUrls();
for(var i = 0; i < imageUrls.length; i++) {
images.push(Evernote.Utils.makeAbsolutePath(serializer.getDocumentBase(), imageUrls[i]).replace(/\s/g, "%20"));
}
callback( {
content : serializer.getSerializedDom(),
imageUrls : images,
docBase : serializer.getDocumentBase()
} );
};
parser.parseAsync( ancestor, false, serializer, resultFunc );
var end = new Date().getTime();
Evernote.Logger.debug( "JSSerializer.serializeSelection(): clipped selection in " + (end - start) + " milliseconds" );
}
catch ( e ) {
Evernote.Logger.error( "JSSerializer.serializeSelection() failed: error = " + e );
throw e;
}
},
serializeSelection : function( range ) {
try {
if( !range ) {
if ( !this.hasSelection() ) {
Evernote.Logger.warn( "JSSerializer.serializeSelection(): no selection to clip" );
return;
}
range = Evernote.Utils.fixIERangeObject(this._selectionFinder.getRange());
if ( !range ) {
Evernote.Logger.warn( "JSSerializer.serializeSelection(): no range in selection" );
return;
}
}
var start = new Date().getTime();
var ancestor = (this._styleStrategy && Evernote.Utils.Selection.getCommonAncestorContainer(range).nodeType == Evernote.Node.TEXT_NODE
&& Evernote.Utils.Selection.getCommonAncestorContainer(range).parentNode) ? Evernote.Utils.Selection.getCommonAncestorContainer(range).parentNode : Evernote.Utils.Selection.getCommonAncestorContainer(range);
while ( typeof Evernote.ClipRules.NON_ANCESTOR_NODES[ ancestor.nodeName.toUpperCase() ] != 'undefined' && ancestor.parentNode ) {
if ( ancestor.nodeName.toUpperCase() == "BODY" ) {
break;
}
ancestor = ancestor.parentNode;
}
var serializer = new Evernote.NodeSerializer( window, new Evernote.ClipFullStylingStrategy() );
var parser = new Evernote.DomParser(window, Evernote.Utils.fixIERangeObject(range));
parser.parse( ancestor, false, serializer );
var end = new Date().getTime();
Evernote.Logger.debug( "JSSerializer.serializeSelection(): clipped selection in " + (end - start) + " milliseconds" );
var images = [];
var imageUrls = serializer.getImagesUrls();
for(var i = 0; i < imageUrls.length; i++) {
images.push(Evernote.Utils.makeAbsolutePath(serializer.getDocumentBase(), imageUrls[i]).replace(/\s/g, "%20"));
}
return {
content : serializer.getSerializedDom(),
imageUrls : images,
docBase : serializer.getDocumentBase()
}
}
catch ( e ) {
Evernote.Logger.error( "JSSerializer.serializeSelection() failed: error = " + e );
throw e;
}
},
hasSelection : function() {
Evernote.Logger.debug( "Clip.hasSelection()" );
if ( this._selectionFinder.hasSelection() ) {
return true;
}
else {
this._selectionFinder.find( true );
return this._selectionFinder.hasSelection();
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Represents JQuery loader that allow to have two versions of JQuery loaded on the same page
* @type {Object}
*/
Evernote.JQueryLoader = {
/**
* Initializes jquery instance on global Evernote context
*/
initJQuery : function() {
Evernote.JQuery = $.noConflict(true);
}
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ClipNotificator = function ClipNotificator() {
};
Evernote.ClipNotificator.WAIT_CONTAINER_ID = "evernoteContentClipperWait";
Evernote.ClipNotificator.SHOW_WAIT_MIN_TIME = 2000;
Evernote.ClipNotificator.prototype.showCopyNotification = function( doc, useAutoHide ) {
Evernote.Logger.debug( "ClipNotificator.showCopyNotification()" );
try {
var wait = this.getWaitContainer( doc, Evernote.Addin.getLocalizedMessage(Evernote.Messages.CLIPPING) );
wait.style.opacity = "1";
this.centerBox(wait);
if ( doc.body ) {
doc.body.appendChild( wait );
}
if (useAutoHide)
{
var self = this;
var timeout = this.constructor.SHOW_WAIT_MIN_TIME;
setTimeout( function() {
self.clearWait( doc );
}, timeout );
}
}
catch ( e ) {
Evernote.Logger.error( "ClipNotificator.showCopyNotification() failed: error = " + e );
}
};
Evernote.ClipNotificator.prototype.centerBox = function( container ) {
var topPosition = ((document.documentElement.scrollTop || document.body.scrollTop) + ((((document.documentElement.clientHeight || document.body.clientHeight) + (!container.offsetHeight && 0)) / 2) >> 0));
var leftPosition = (((document.documentElement.clientWidth || document.body.clientWidth) / 2) - (container.offsetWidth / 2));
container.style.position = "absolute";
container.style.top = (topPosition-20) + "px";
container.style.left = (leftPosition - 90) + "px";
};
Evernote.ClipNotificator.prototype.getWaitContainer = function( doc, msg ) {
Evernote.Logger.debug( "ClipNotificator.getWaitContainer()" );
var container = doc.getElementById( this.constructor.WAIT_CONTAINER_ID );
if ( !container ) {
container = doc.createElement( "evernotediv" );
if(Evernote.Utils.isQuirkMode()) {
container.className = "quirk-mode-container";
}
container.id = this.constructor.WAIT_CONTAINER_ID;
var wait = doc.createElement( "div" );
wait.id = this.constructor.WAIT_CONTAINER_ID + "Content";
if(Evernote.BrowserDetection.isLessThanIE9()) {
wait.className = "content-less-than-nine-container";
}
container.appendChild( wait );
var center = doc.createElement( "center" );
wait.appendChild( center );
var spinner = doc.createElement( "div" );
spinner.id = "evernote-spinner-container";
Evernote.GlobalUtils.absolutizeImages(spinner, "images/icon_scissors.png");
center.appendChild( spinner );
var text = doc.createElement( "span" );
text.id = this.constructor.WAIT_CONTAINER_ID + "Text";
center.appendChild( text );
container._waitMsgBlock = text;
container._waitMsgBlock.appendChild( doc.createTextNode( msg ) );
}
return container;
};
Evernote.ClipNotificator.prototype.clearWait = function( doc ) {
Evernote.Logger.debug( "ClipNotificator.clearWait()" );
var wait = doc.getElementById( this.constructor.WAIT_CONTAINER_ID );
if ( wait ) {
wait.style.opacity = "0";
setTimeout( function() {
if ( wait.parentNode ) {
wait.parentNode.removeChild( wait );
}
}, 1000 );
}
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Represents clipper object that is capable of clipping elements from pages or clip elements based on preferences.
*/
Evernote.Clipper = {
_serializer : Evernote.JSSerializer,
_clipNotifier : new Evernote.ClipNotificator(),
_defaultOptions : {
title: PageContext.title,
tags: [],
comments: "",
notebookUid: -1
},
/**
* Clips article element (one that user selected or default if no selection was made).
*/
clipArticle : function(options) {
var currentOptions = this.initOptions(options);
this._clipNotifier.showCopyNotification(document);
var self = this;
setTimeout(function() {
var article = Evernote.contentPreviewer.getArticleElement();
if(!article) {
article = Evernote.pageInfo.getDefaultArticle(function(article) {});
}
var resultFunc = function(serializedDom) {
self._clipNotifier.clearWait(document);
Evernote.Addin.clipNote(currentOptions.comments + serializedDom.content, currentOptions, PageContext.url, serializedDom.imageUrls, true, document);
};
self._serializer.serializeAsync(article, false, resultFunc);
}, 100);
},
initOptions: function(options) {
if(!options)
options = this._defaultOptions;
options = Evernote.JQuery.extend({}, this._defaultOptions, options);
if(!options.title || Evernote.JQuery.trim(options.title).length == 0)
options.title = Evernote.Addin.getLocalizedMessage(Evernote.Messages.UNTITLED_NOTE);
options.title = Evernote.JQuery.trim(Evernote.Utils.cutToLength(options.title, 255, " "));
return options;
},
/**
* Clips full page.
*/
clipFullPage : function(options) {
Evernote.Logger.debug("Clipper: clipFullPage");
var currentOptions = this.initOptions(options);
this._clipNotifier.showCopyNotification(document);
var self = this;
setTimeout(function() {
Evernote.Logger.debug("Start clipping of full page");
var resultFunc = function(serializedDom) {
self._clipNotifier.clearWait(document);
Evernote.Logger.debug("Image urls " + JSON.stringify(serializedDom.imageUrls));
Evernote.Logger.debug("Send clip to EN");
Evernote.Addin.clipNote(currentOptions.comments + serializedDom.content, currentOptions, PageContext.url, serializedDom.imageUrls, true, document);
};
self._serializer.serializeAsync(null, true, resultFunc);
}, 100);
},
/**
* Clips url with favicon (if favicon is recognized)
*/
clipUrl : function(options) {
var currentOptions = this.initOptions(options);
this._clipNotifier.showCopyNotification(document, true);
setTimeout(function() {
var content = Evernote.GlobalUtils.createUrlClipContent(PageContext.title, PageContext.url, PageContext.getFavIconUrl());
Evernote.Addin.clipNote(currentOptions.comments + content, currentOptions, PageContext.url, PageContext.getFavIconUrl(), true, document);
}, 100);
},
/**
* Clips selection from the page.
*/
clipSelection : function( range, options ) {
var currentOptions = this.initOptions(options);
this._clipNotifier.showCopyNotification(document);
var self = this;
setTimeout(function() {
var resultFunc = function(serializedDom) {
self._clipNotifier.clearWait(document);
if(serializedDom) {
Evernote.Addin.clipNote(currentOptions.comments + serializedDom.content, currentOptions, PageContext.url, serializedDom.imageUrls, true, document);
}
};
var serializedDom = self._serializer.serializeSelectionAsync( range, resultFunc );
}, 100);
},
/**
* Clips image from the page.
*/
clipImage : function(options ) {
if (!options.imageElement) {
Evernote.Logger.debug("clipImage Empty element");
return;
}
var currentOptions = this.initOptions(options);
this._clipNotifier.showCopyNotification(document);
var self = this;
setTimeout(function() {
Evernote.Logger.debug("Start clipping of image");
var resultFunc = function(serializedDom) {
self._clipNotifier.clearWait(document);
Evernote.Logger.debug("Image urls " + JSON.stringify(serializedDom.imageUrls));
Evernote.Logger.debug("Send clip to EN");
Evernote.Addin.clipNote(currentOptions.comments + serializedDom.content, currentOptions, PageContext.url, serializedDom.imageUrls, true, document);
};
self._serializer.serializeAsync(options.imageElement, false, resultFunc);
}, 100);
},
/**
* Clips part of the page, defined in option (url, article or full page) or selection if presented.
*/
clipWithOptions : function(clipOptions) {
var options = {
notebookUid: function() {
var savedNotebookUid = Evernote.Options.selectedNotebookUid;
var notebook = Evernote.NotebooksLoader.getNotebookByUid(savedNotebookUid);
if(!notebook) {
return -1;
} else {
return notebook.uid;
}
},
imageElement: EvernoteExternal.imageElement
};
if(clipOptions.getClipAction() == Evernote.ClipperActions.CLIP_SELECTION && Evernote.Utils.hasSelection(window)) {
Evernote.Clipper.clipSelection(null, options);
}
else if(clipOptions.getClipAction() == Evernote.ClipperActions.CLIP_URL) {
Evernote.Clipper.clipUrl(options);
} else if(clipOptions.getClipAction() == Evernote.ClipperActions.CLIP_FULL_PAGE) {
Evernote.Clipper.clipFullPage(options);
} else if(clipOptions.getClipAction() == Evernote.ClipperActions.CLIP_IMAGE) {
Evernote.Clipper.clipImage(options);
} else {
Evernote.Logger.warn("Unknown option is specified : " + clipOptions.getClipAction());
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ClipOptions = function ClipOptions(data) {
this.clipAction = data.clipAction;
};
Evernote.ClipOptions.prototype.getClipAction = function() {
return this.clipAction;
};</script><script charset="ANSI" defer="" type="text/javascript">function ContentVeil() {
Evernote.Logger.debug(document);
var veil = document.createElement("div");
var inner = document.createElement("div");
veil.appendChild(inner);
veil.style.boxSizing = "border-box";
veil.style.borderStyle = "solid";
var scroller = new Evernote.Scroller( window );
try {
veil.style.borderColor = "rgba(0, 0, 0, 0.7)";
} catch (e) {
veil.style.borderColor = "rgb(0, 0, 0)";
veil.className = "evernote-top-fixed-position-quirks";
}
inner.style.borderWidth = "4px";
inner.style.borderStyle = "solid";
try {
inner.style.borderColor = "rgba(255, 255, 0, 0.7)";
} catch (e) {
inner.style.borderColor = "rgb(255, 255, 0)";
}
inner.style.height = "100%";
inner.style.width = "100%";
inner.style.boxSizing = "border-box";
// We keep a record of what we're currently showing (at least in some cases) so that we can update it in case the
// state of the page changes (like if the user scrolls).
var currentlyShownRect = null;
var currentRectOffsetTop = 0;
var currentRectOffsetLeft = 0;
var currentlyStatic = false;
function reset() {
currentlyShownRect = null;
currentRectOffsetTop = 0;
currentRectOffsetLeft = 0;
showElements("embed");
showElements("object");
showElements("iframe");
veil.style.position = "fixed";
veil.style.left = "0px";
veil.style.zIndex = "2147483646";
if(Evernote.Utils.isQuirkMode() && !Evernote.BrowserDetection.isIE10orGreater()) {
veil.style.position = "absolute";
veil.className = "evernote-top-fixed-position-quirks";
}
else {
veil.style.top = "0px";
}
blank();
}
function blank() {
if((Evernote.Utils.isQuirkMode() || Evernote.BrowserDetection.isLessThanIE9()) && !Evernote.BrowserDetection.isIE10orGreater()) {
veil.style.width = "0px";
veil.style.height = "0px";
}
else {
veil.style.height = Evernote.Utils.innerHeight() + "px";
veil.style.width = Evernote.Utils.innerWidth() + "px";
}
}
function gray() {
show();
inner.style.display = "none";
}
function show() {
Evernote.Logger.debug("Content veil show");
inner.style.display = "";
veil.style.backgroundColor = "";
if (!Evernote.ElementExtension.hasParentNode(veil)) {
document.body.appendChild(veil);
}
}
function hide() {
veil.style.borderLeftWidth = Evernote.Utils.innerWidth()/2 + "px";
veil.style.borderRightWidth = Evernote.Utils.innerWidth()/2 + "px";
veil.style.borderBottomWidth = Evernote.Utils.innerHeight()/2 + "px";
veil.style.borderTopWidth = Evernote.Utils.innerHeight()/2 + "px";
if (Evernote.ElementExtension.hasParentNode(veil)) {
veil.parentNode.removeChild(veil);
}
}
// Makes a rectangle bigger in all directions by the number of pixels specified (or smaller, if 'amount' is
// negative). Returns the new rectangle.
function expandRect(rect, amount) {
return {
top: (rect.top - amount),
left: (rect.left - amount),
bottom: (rect.bottom + amount),
right: (rect.right + amount),
width: (rect.width + (2 * amount)),
height: (rect.height + (2 * amount))
};
}
function scrollToRect(rect) {
var sLeft = document.documentElement.scrollLeft;
var sTop = document.documentElement.scrollTop;
var left = rect.left - (Evernote.Utils.innerWidth() / 2) + sLeft;
var top = rect.top - (Evernote.Utils.innerHeight() / 2) + sTop;
scroller.scrollTo( { x: left, y: top }, 120, 20 );
}
// DrawStroke is obsolete, it is now always "true".
function revealRect(rect, drawStroke, staticView) {
// Save this info.
currentlyShownRect = rect;
currentRectOffsetTop = Evernote.Utils.scrollTop();
currentRectOffsetLeft = Evernote.Utils.scrollLeft();
currentlyStatic = staticView;
// We expand the rectangle for two reasons.
// 1) we want to expand it by the width of the stroke, so that when we draw out outline, it doesn't overlap our
// content.
// 2) We want to leave a little extra room around the content for aesthetic reasons.
rect = expandRect(rect, 8);
var x = rect.left;
var y = rect.top;
var width = rect.width;
var height = rect.height;
var veilWidth = Evernote.Utils.innerWidth(); //veil.style.width.replace("px", "");
var veilHeight = Evernote.Utils.innerHeight(); //veil.style.height.replace("px", "");
Evernote.Logger.debug("Veil width " + veilWidth);
Evernote.Logger.debug("Veil height " + veilHeight);
var offScreen = false;
if (y + height < 0) {
Evernote.Logger.debug("y + height < 0");
offScreen = true;
}
else if (y > veilHeight) {
Evernote.Logger.debug("y > veilHeight");
offScreen = true;
}
else if (x + width < 0) {
Evernote.Logger.debug("x + width < 0");
offScreen = true;
}
else if (x > veilWidth) {
Evernote.Logger.debug("x > veilWidth");
offScreen = true;
}
Evernote.Logger.debug("Is offscreen " + offScreen);
if (offScreen) {
veil.style.borderLeftWidth = veilWidth/2 + "px";
veil.style.borderRightWidth = veilWidth/2 + "px";
veil.style.borderTopWidth = veilHeight/2 + "px";
veil.style.borderBottomWidth = veilHeight/2 + "px";
inner.style.display = "none";
return;
}
Evernote.Logger.debug("Show rect " + JSON.stringify(rect));
inner.style.display = "block";
veil.style.borderLeftWidth = Math.max(x, 0) + "px";
veil.style.borderTopWidth = Math.max(y, 0) + "px";
veil.style.borderRightWidth = Math.max((veilWidth - x - width), 0) + "px";
veil.style.borderBottomWidth = Math.max((veilHeight - y - height), 0) + "px";
veil.style.width = veilWidth + "px";
veil.style.height = veilHeight + "px";
/*
veil.style.width = (veilWidth - (Math.max(x, 0) + Math.max((veilWidth - x - width), 0))) + "px";
veil.style.height = (veilHeight - (Math.max(y, 0) + Math.max((veilHeight - y - height), 0))) + "px";
*/
Evernote.Logger.debug("revealRect finished");
}
function revealStaticRect(rect, drawStroke) {
revealRect(rect, drawStroke, true);
}
function outlineElement(element, scrollTo) {
// See notes in Preview.js for why we use this method instead of just calling element.getBoundingClientRect().
if (scrollTo) {
Evernote.Logger.debug("ContentVeil:scrollIntoViewIfNeeded ");
element.scrollIntoView(true);
}
var rect = Evernote.contentPreviewer.computeDescendantBoundingBox(element);
Evernote.Logger.debug("Calculated rect " + rect);
if (rect) {
var mutableRect = {
top: rect.top,
bottom: rect.bottom,
left: rect.left,
right: rect.right,
width: rect.width,
height: rect.height
}
// We don't want to adjust ourselves into odd positions if the page is scrolled.
var sLeft = Evernote.Utils.scrollLeft();
var sTop = Evernote.Utils.scrollTop();
var BORDER_MIN = 9;
if (mutableRect.left < (BORDER_MIN - sLeft)) {
mutableRect.width -= (BORDER_MIN - sLeft) - mutableRect.left;
mutableRect.left = (BORDER_MIN - sLeft);
}
if (mutableRect.top < (BORDER_MIN - sTop)) {
mutableRect.height -= (BORDER_MIN - sTop) - mutableRect.top;
mutableRect.top = (BORDER_MIN - sTop);
}
// Get the wider of our two possible widths.
var width = Math.max(document.body.scrollWidth, Evernote.Utils.innerWidth());
if (mutableRect.right > (width - BORDER_MIN - sLeft)) {
mutableRect.right = (width - BORDER_MIN - sLeft);
mutableRect.width = mutableRect.right - mutableRect.left;
}
Evernote.Logger.debug("Mutable record " + mutableRect.top + ", " + mutableRect.left + ", " + mutableRect.right + ", " + mutableRect.bottom + ", " + mutableRect.width + ", " + mutableRect.height);
Evernote.Logger.debug("ContentVeil:reset ");
reset();
Evernote.Logger.debug("ContentVeil:revealRect ");
revealRect(mutableRect, true);
Evernote.Logger.debug("Hide elements embeded");
hideElements("embed", element);
hideElements("object", element);
Evernote.Logger.debug("Hide elements iframe");
hideElements("iframe", element);
Evernote.Logger.debug("Show it");
show();
}
else {
Evernote.Logger.warn("Couldn't create rectangle from element: " + element.toString());
}
}
function hideAllActiveObjects() {
hideElements("embed");
hideElements("object");
hideElements("iframe");
}
function hideElements (tagName, exceptInElement) {
var els = document.getElementsByTagName(tagName);
for (var i = 0; i < els.length; i++) {
els[i].enSavedVisibility = els[i].style.visibility;
els[i].style.visibility = "hidden";
}
}
function showElements (tagName, inElement) {
if (!inElement) {
inElement = document;
}
var els = inElement.getElementsByTagName(tagName);
for (var i = 0; i < els.length; i++) {
if (typeof els[i].enSavedVisibility !== "undefined") {
els[i].style.visibility = els[i].enSavedVisibility;
try {
delete els[i].enSavedVisibility;
} catch(e) {
els[i].enSavedVisibility = undefined;
}
}
}
}
// If we're currently showing a rectangle, and it's not static, we'll redraw on scroll.
var onScrollHandle = function(e) {
Evernote.Logger.debug("On scroll start");
Evernote.Logger.debug("currentlyShownRect " + JSON.stringify(currentlyShownRect));
Evernote.Logger.debug("currentlyStatic " + currentlyStatic);
if (currentlyShownRect && !currentlyStatic) {
var rect = {
top: currentlyShownRect.top,
bottom: currentlyShownRect.bottom,
left: currentlyShownRect.left,
right: currentlyShownRect.right,
width: currentlyShownRect.width,
height: currentlyShownRect.height
};
Evernote.Logger.debug("Evernote.Utils.scrollTop() " + Evernote.Utils.scrollTop());
Evernote.Logger.debug("Evernote.Utils.scrollLeft() " + Evernote.Utils.scrollLeft());
var vert = Evernote.Utils.scrollTop() - currentRectOffsetTop;
var horiz = Evernote.Utils.scrollLeft() - currentRectOffsetLeft;
if (!vert && !horiz) {
Evernote.Logger.debug("No vertical and horizontal");
return;
}
rect.top -= vert;
rect.bottom -= vert;
rect.left -= horiz;
rect.right -= horiz;
blank();
revealRect(rect);
}
};
if (window.attachEvent)
window.attachEvent("onscroll", onScrollHandle);
else if (window.addEventListener)
window.addEventListener("scroll", onScrollHandle, false);
else
Evernote.Logger.error( "ContentVeil can't attachEvent" );
// Public API:
this.reset = reset;
this.show = show;
this.gray = gray;
this.hide = hide;
this.revealRect = revealRect;
this.revealStaticRect = revealStaticRect;
this.outlineElement = outlineElement;
this.expandRect = expandRect;
this.hideAllActiveObjects = hideAllActiveObjects;
this.scrollToRect = scrollToRect;
Evernote.Logger.debug("End content veil");
}</script><script charset="ANSI" defer="" type="text/javascript">function PageInfo() {
// This is a map of hostnames (for hostnames that begin with 'www.', the 'www.' will be stripped off first, so don't
// include it in your lookup string) to CSS selectors. When we try and locate an article in a page, we'll see if we
// can find the doamin for the page in this list, and if so, we'll try and find an element that matches the given
// selector. If no element is returned, we'll fall back to the heuristic approach.
var specialCases = {
"penny-arcade.com": "div.contentArea > div.comic > img",
"aspicyperspective.com": "div.entry-content",
"thewirecutter.com": "div#content",
"katespade.com": "div#pdpMain",
"threadless.com": "section.product_section",
"yelp.com": "div#bizBox",
"flickr.com": "div#photo",
"instagr.am": "div.stage > div.stage-inner",
"stackoverflow.com": "div#mainbar",
"makeprojects.com": "div#guideMain",
"cookpad.com": "div#main",
"imgur.com": "div.image",
"smittenkitchen.com": "div.entry",
"allrecipes.com": "div#content-wrapper",
"qwantz.com": "img.comic",
"questionablecontent.net": "img#strip",
"cad-comic.com": "div#content"
}
var useFoundImage = [
"xkcd.com"
]
// These are the items we're trying to collect. This first block is trivial.
var containsImages = Boolean(document.getElementsByTagName("img").length > 0);
var documentWidth = document.width;
var documentHeight = document.height;
var url = document.location.href;
var documentLength = document.body.textContent ? document.body.textContent.length : 0;
// These take slightly more work and are initialized only when requested.
var article = null;
var articleBoundingClientRect = null;
var selection = false; // This is easy to get, but is always "false" at load time until the user selects something.
var selectionIsInFrame = false;
var documentIsFrameset = false;
var selectionFrameElement = null;
var recommendationText = null;
// Internal state variables to keep us duplicating work.
var hasCheckedArticle = false;
// Experimental recognition of 'image' pages (like photo sites and comics).
function findImage() {
var imgs = document.getElementsByTagName("img");
var biggest = null;
var biggestArea = 0;
for (var i = 0; i < imgs.length; i++) {
var style = Evernote.ElementExtension.getComputedStyle(imgs[i]);
var width = style.width.replace(/[^0-9.-]/g, "");
var height = style.height.replace(/[^0-9.-]/g, "");
var area = width * height;
if (!biggest || area > biggestArea) {
biggest = imgs[i];
biggestArea = area;
}
}
return biggest;
}
function getAncestors(node) {
var an = [];
while (node) {
an.unshift(node);
node = node.parentNode;
}
return an;
}
function getDeepestCommonNode(nodeList1, nodeList2) {
var current = null;
for (var i = 0; i < nodeList1.length; i++) {
if (nodeList1[i] === nodeList2[i]) {
current = nodeList1[i];
}
else {
break;
}
}
return current;
}
function getCommonAncestor(nodeList) {
if (!nodeList.length) return null;
if (nodeList.length == 1) return nodeList[0];
var lastList = getAncestors(nodeList[0]);
var node = null;
for (var i = 1; i < nodeList.length; i++) {
var list = getAncestors(nodeList[i]);
node = getDeepestCommonNode(lastList, list);
lastList = getAncestors(node);
}
return node;
}
function clearlyCallback(data, callback) {
Evernote.Logger.debug("Clearly callback invoked");
findImage();
// See if we should special-case this.
var host = getHostname();
if (specialCases[host])
{
var candidate = Evernote.ElementExtension.querySelector(specialCases[host]);
if (candidate) {
Evernote.Logger.debug("Found article in specialCases");
article = candidate;
articleBoundingClientRect = Evernote.ElementExtension.getBoundingClientRect(article);
}
}
// Or see if it's a special case image page.
else if (Evernote.ArrayExtension.indexOf(useFoundImage, host) != -1) {
article = findImage();
if (article) {
Evernote.Logger.debug("Found article in image");
articleBoundingClientRect = Evernote.ElementExtension.getBoundingClientRect(article);
}
}
// If it's not a special case, see if it's a single image.
if (!article) {
var imageTypes = ['jpeg', 'jpg', 'gif', 'png'];
var urlExtension = document.location.href.replace(/^.*\.(\w+)$/, "$1");
if (urlExtension && (Evernote.ArrayExtension.indexOf(imageTypes, urlExtension) != -1)) {
var candidate = Evernote.JQuery("body > img");
if (candidate.length > 0) {
Evernote.Logger.debug("Found article in a single image");
article = candidate.get(0);
articleBoundingClientRect = Evernote.ElementExtension.getBoundingClientRect(article);
}
}
}
// If we still didn't find an article, let's see if maybe it's in a frame. Cleary fails on frames so we try this
// check before we use our clearly info.
if (!article) {
if (document.body.nodeName.toLowerCase() == "frameset") {
documentIsFrameset = true;
var frame = findBiggestFrame();
if (frame && frame.contentDocument && frame.contentDocument.documentElement) {
selectionFrameElement = frame;
article = frame.contentDocument.documentElement;
articleBoundingClientRect = Evernote.ElementExtension.getBoundingClientRect(article);
}
}
}
// If we didn't use any of our special case handling, we'll use whatever clearly found.
if (!article) {
Evernote.Logger.debug("Use clearly find article");
if (data && data._elements && data._elements.length) {
article = data._elements[0];
if (data._elements.length > 1) {
// This will include *all* clearly elements (and whatever else in in between them).
article = getCommonAncestor(data._elements);
// This includes *just the last (and therefore most important)* element from the clearly detection.
// article = data._elements[data._elements.length - 1];
}
if (article.nodeType === ( window.Node ? window.Node.TEXT_NODE : 1)) {
article = article.parentNode;
}
}
}
if(article) {
if(Evernote.JQuery(article).closest("#evernote-content").length != 0)
article = undefined;
}
// If clearly found nothing (because it failed), then use the body of the document.
if (!article) {
article = document.body;
}
hasCheckedArticle = true;
callback();
}
// This will try and determine the 'default' page article. It will only run once per page, but it's specifically
// called only on demand as it can be expensive.
function findArticle(callback) {
function afterInject() {
// If we'd previously computed an article element, but it's lost its parent or become invisible, then we'll try
// and re-compute the article. This can happen if, for example the page dynamically udaptes itself (like showing
// the latest news article in a box that updates periodically). This doesn't guarantee that we clip something
// sane if this happens, (if the page re-writes itself while a clip is taking place, the results are
// indeterminate), but it will make such things less likely.
if (article &&
(!article.parentNode || !article.getBoundingClientRect || Evernote.ElementExtension.getBoundingClientRect(article).width == 0)) {
article = null;
hasCheckedArticle = false;
}
Evernote.Logger.debug("afterInject");
if (!hasCheckedArticle) {
Evernote.Logger.debug("no article");
if (!window || !window.ClearlyComponent)
{
Evernote.Logger.warn("Couldn't find clearly!");
clearlyCallback(null, callback);
}
else {
Evernote.Logger.debug("Call clearly to select article");
try {
window.ClearlyComponent.getContentElementAndHTML(window, function(data){clearlyCallback(data, callback)});
} catch(e) {
Evernote.Logger.error("Failed to find article by clearly due to error " + e);
clearlyCallback(null, callback);
}
}
}
// If the page is big enough, clearly is excruciatingly slow. We'll jsut get the whole page.
// @TODO: Maybe clearly can get faster.
else if (document.body.innerHTML.length > (1024 * 1024)) {
Evernote.Logger.warn("Page over 1mb, skipping article detection.");
clearlyCallback(null, callback);
}
else {
Evernote.Logger.debug("callback");
callback();
}
}
afterInject();
}
function findBiggestFrame() {
var frames = document.getElementsByTagName("frame");
var candidate = null;
var candidateSize = 0;
for (var i = 0; i < frames.length; i++) {
if (frames[i].width && frames[i].height) {
var area = frames[i].width * frames[i].height;
if (area > candidateSize) {
candidate = frames[i];
candidateSize = area;
}
}
}
return candidate;
}
function getHostname() {
var match = document.location.href.match(/^.*?:\/\/(www\.)?(.*?)(\/|$)/);
if (match) {
return match[2];
}
return null;
}
function getDefaultArticle(callback) {
Evernote.Logger.debug("getDefaultArticle");
findArticle(function(){callback(article)});
// Article already exists, so we'll return it.
if (article) return article;
}
// Looks for selections in the current document and descendent (i)frames.
// Returns the *first* non-empty selection.
function getSelection() {
// First we check our main window and return a selection if that has one.
var selection = window.getSelection();
if (selection && selection.rangeCount && !selection.isCollapsed) {
return selection;
}
// Then we'll try our frames and iframes.
var docs = [];
var iframes = document.getElementsByTagName("iframe");
for (var i = 0; i < iframes.length; i++) {
docs.push(iframes[i]);
}
var frames = document.getElementsByTagName("frame");
for (var i = 0; i < frames.length; i++) {
docs.push(frames[i]);
}
var urlBase = document.location.href.replace(/^(https?:\/\/.*?)\/.*/i, "$1").toLowerCase();
for (var i = 0; i < docs.length; i++) {
// If frames/iframes fail a same origin policy check, then they'll through annoying errors, and we wont be able
// to access them anyway, so we attempt to skip anything that wont match.
if (docs[i].src && docs[i].src.toLowerCase().substr(0, urlBase.length) !== urlBase) {
continue;
}
var doc = docs[i].contentDocument;
if (doc) {
var frameSelection = doc.getSelection();
if (frameSelection && frameSelection.rangeCount && !frameSelection.isCollapsed) {
selectionIsInFrame = true;
selectionFrameElement = docs[i];
return frameSelection;
}
}
else {
Evernote.Logger.warn("iframe contained no Document object.");
}
}
// Didn't find anything.
return null;
}
function getText(node, soFar, maxLen) {
if (node.nodeType == Evernote.Node.TEXT_NODE) {
var trimmed = node.textContent.trim().replace(/\s+/g, " ");
if (trimmed === " " || trimmed === "") return soFar;
return soFar + " " + trimmed;
}
var banned = [
"script",
"noscript"
];
if (node.nodeType == Evernote.Node.ELEMENT_NODE) {
if (Evernote.ArrayExtension.indexOf(banned, node.nodeName.toLowerCase()) == -1) {
for (var i = 0; i < node.childNodes.length; i++) {
soFar = getText(node.childNodes[i], soFar, maxLen);
if (soFar.length > maxLen) {
return soFar;
}
}
}
}
return soFar;
}
function getRecommendationText() {
var text = "";
var MAX_LEN = 5000;
var selection = getSelection();
if (selection) {
var df = selection.getRangeAt(0).cloneContents();
var div = document.createElement("div");
div.appendChild(df);
text = getText(div, "", MAX_LEN);
}
else if (article) {
text = getText(article, "", MAX_LEN);
}
else {
text = getText(document.body, "", MAX_LEN);
}
text = document.title + " " + text;
return text;
}
// Note: you must call getSelection() first to populate this field!
function getSelectionFrame() {
return selectionFrameElement;
}
function checkClearly() {
var clearlyDoc = Evernote.ElementExtension.querySelector("iframe#readable_iframe");
if (clearlyDoc) clearlyDoc = clearlyDoc.contentDocument;
if (clearlyDoc) clearlyDoc = Evernote.ElementExtension.querySelector("body#body div#box", clearlyDoc);
if (clearlyDoc) {
article = clearlyDoc;
articleBoundingClientRect = Evernote.ElementExtension.getBoundingClientRect(article);
}
}
// @TODO: This is fairly incomplete.
function getFavIconUrl() {
var links = document.getElementsByTagName("link");
var i;
for (i = 0; i < links.length; i++) {
if (links[i].rel) {
var rels = links[i].rel.toLowerCase().split(/\s+/);
if (Evernote.ArrayExtension.indexOf(rels, "icon") !== -1) {
// Found it!
return links[i].href;
}
}
}
return null;
}
function _getInfoRequestHandler(data, request, sender, sendResponse) {
var isSelected = getSelection();
checkClearly();
var response = {
containsImages: containsImages,
documentWidth: documentWidth,
documentHeight: documentHeight,
url: url,
selection: (isSelected !== null),
selectionIsInFrame: selectionIsInFrame,
documentLength: document.body.textContent.length,
articleBoundingClientRect: articleBoundingClientRect,
article: (article != null),
recommendationText: getRecommendationText(),
favIconUrl: getFavIconUrl(),
documentIsFrameset: documentIsFrameset
};
sendResponse(response);
}
function getInfoRequestHandler(request, sender, sendResponse) {
findArticle(function(data){_getInfoRequestHandler(data, request, sender, respondWithInfo)});
}
// Public API:
this.getDefaultArticle = getDefaultArticle;
this.getSelection = getSelection;
this.getSelectionFrame = getSelectionFrame;
this.getFavIconUrl = getFavIconUrl;
}</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Scroller = function Scroller( tab ) {
this.initialize( tab );
};
Evernote.Scroller.prototype._tab = null;
Evernote.Scroller.prototype.initialize = function ( tab ) {
this._tab = tab;
var scrollX = (this._tab.pageXOffset !== undefined) ? this._tab.pageXOffset : (this._tab.document.documentElement || this._tab.document.body.parentNode ||this._tab.document.body).scrollLeft;
var scrollY = (this._tab.pageYOffset !== undefined) ? this._tab.pageYOffset : (this._tab.document.documentElement || this._tab.document.body.parentNode || this._tab.document.body).scrollTop;
this.initialPoint = {
x: scrollX,
y: scrollY
};
};
Evernote.Scroller.prototype.scrollTo = function ( endPoint, time, resolution ) {
this.abort();
this.endPoint = endPoint;
this.step = 0;
this.calculatePath( time, resolution );
var self = this;
this.proc = setInterval( function () {
if ( !self.doScroll() ) {
self.abort();
}
},
resolution );
};
Evernote.Scroller.prototype.calculatePath = function ( time, resolution ) {
this.path = [];
var sx = this.initialPoint.x;
var sy = this.initialPoint.y;
var ex = this.endPoint.x;
var ey = this.endPoint.y;
var k = (Math.PI * resolution) / time;
for ( var i = -(Math.PI / 2); i < (Math.PI / 2); i += k ) {
var c = ((1 + Math.sin( i )) / 2);
this.path.push( {
x:(sx + c * (ex - sx)),
y:(sy + c * (ey - sy))
} );
}
};
Evernote.Scroller.prototype.doScroll = function () {
var s = this.path[++this.step];
if ( !s ) {
return false;
}
var view = this._tab.document.defaultView || this._tab;
view.scrollTo( s.x, s.y );
return true;
};
Evernote.Scroller.prototype.abort = function () {
if ( this.proc ) {
clearInterval( this.proc );
this.proc = null;
}
};</script><script charset="ANSI" defer="" type="text/javascript">function ContentPreview() {
Evernote.Logger.debug("Start creating preview box");
var contentVeil = new ContentVeil();
Evernote.Logger.debug("End creating preview box");
// Stores a reference to the last element that we used as a preview.
var previewElement = null;
var article = null;
function buildPreviewLegend() {
Evernote.Logger.debug("buildPreviewLegend: start");
var legend = document.createElement("div");
legend.id = "evernotePreviewLegend";
legend.className = "evernotePreviewLegend";
if(Evernote.Utils.isQuirkMode() || Evernote.BrowserDetection.isLessThanIE9()) {
legend.className += " quirk-mode";
legend.className += " evernote-preview-position-top";
}
legend.dir = "ltr"; // It ends up backwards on right-to-left pages otherwise.
var nudgeImgs = [
// Element class name Message identifier
["icon-arrow-up", { message: Evernote.Messages.EXPAND_SELECTION, image: "images/nudge-icons/nudge-icon-arrow-up.png"} ],
["icon-arrow-down", { message: Evernote.Messages.SHRINK_SELECTION, image: "images/nudge-icons/nudge-icon-arrow-down.png"}],
["icon-arrow-lr", { message: Evernote.Messages.MOVE_SELECTION, image: "images/nudge-icons/nudge-icon-arrow-lr.png"}],
["icon-return", { message: Evernote.Messages.CLIP_ARTICLE_HINT, image: "images/nudge-icons/nudge-icon-return.png"}]
];
var ul = document.createElement("UL");
Evernote.Logger.debug("buildPreviewLegend: populate container");
for (var i = 0; i < nudgeImgs.length; i++) {
var li = document.createElement("li");
if(i == nudgeImgs.length - 1)
li.className = "last";
var div = document.createElement("div");
var message = document.createTextNode(Evernote.Addin.getLocalizedMessage(nudgeImgs[i][1].message));
div.className = "keyIcon " + nudgeImgs[i][0];
Evernote.GlobalUtils.absolutizeImages(div, nudgeImgs[i][1].image);
li.appendChild(div);
var messageContainer = document.createElement("span");
messageContainer.appendChild(message);
li.appendChild(messageContainer);
var clearDiv = document.createElement("div");
div.style.clear = "both";
li.appendChild(clearDiv);
ul.appendChild(li);
}
Evernote.Logger.debug("buildPreviewLegend: populate container end");
legend.appendChild(ul);
return legend;
}
Evernote.Logger.debug("Build preview legend");
var previewLegend = buildPreviewLegend();
Evernote.Logger.debug("End Build preview legend");
function showPreviewLegend() {
if (!Evernote.ElementExtension.hasParentNode(previewLegend)) {
document.body.appendChild(previewLegend);
}
var className = " visible";
if(Evernote.Utils.isQuirkMode()) {
className = " preview-visible";
}
previewLegend.className = previewLegend.className.replace(/\s*hidden|visible|preview-visible|preview-hidden\s*/, "");
previewLegend.className += className;
}
function hidePreviewLegend() {
var className = " hidden";
if(Evernote.Utils.isQuirkMode()) {
className = " preview-hidden";
}
previewLegend.className = previewLegend.className.replace(/\s*hidden|visible|preview-hidden|preview-visible\s*/, "");
previewLegend.className += className;
}
function removePreviewLegend() {
if (Evernote.ElementExtension.hasParentNode(previewLegend)) {
previewLegend.parentNode.removeChild(previewLegend);
}
}
function buildUrlElement() {
var urlEl = document.createElement("div");
urlEl.id = "evernotePreviewContainer";
var className = "evernotePreviewContainer evernotePreviewUrlContainer";
if(Evernote.Utils.isQuirkMode()) {
className += " evernote-middle-fixed-position-quirks"
}
urlEl.className = className;
return urlEl;
}
Evernote.Logger.debug("Build url element");
var urlElement = buildUrlElement();
function showUrlElement() {
Evernote.Logger.debug("ContentPreview: showUrlElement start");
if (!Evernote.ElementExtension.hasParentNode(urlElement)) {
document.body.appendChild(urlElement);
}
// Make sure we're centered in the window.
var elStyle = Evernote.ElementExtension.getComputedStyle(urlElement, '');
var w = parseInt(Evernote.StyleElementExtension.getPropertyValue(elStyle, "width"));
var h = parseInt(Evernote.StyleElementExtension.getPropertyValue(elStyle, "height"));
if (w && h) {
urlElement.style.marginLeft = (0 - w / 2) + "px";
urlElement.style.marginTop = (0 - h / 2) + "px";
}
Evernote.Logger.debug("ContentPreview: showUrlElement end");
}
function hideUrlElement() {
if (Evernote.ElementExtension.hasParentNode(urlElement)) {
urlElement.parentNode.removeChild(urlElement);
}
}
function showOverlay() {
previewElement = null;
clear();
contentVeil.reset();
contentVeil.show();
contentVeil.hideAllActiveObjects();
}
function previewUrl() {
previewElement = null;
clear();
contentVeil.reset();
contentVeil.gray();
var title = window.document.title;
var url = PageContext.url;
var favIconUrl =PageContext.getFavIconUrl();
urlElement.innerHTML = Evernote.GlobalUtils.createUrlClipContent(title, url, favIconUrl);
var element = Evernote.JQuery(urlElement);
if(Evernote.Utils.isQuirkMode() && !element.hasClass("evernote-fixed-position-fix")) {
element.addClass("evernote-fixed-position-fix");
Evernote.Utils.fixedPosition(window, element, function() {
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var containerHeight = element.outerHeight();
return scrollTop + (clientHeight - containerHeight) / 2;
}, true);
}
showUrlElement();
contentVeil.hideAllActiveObjects();
}
// This doesn't remove internal state of previewElement, because another script may not have finished clipping until
// after the page looks 'clear'.
function clear() {
contentVeil.reset();
contentVeil.hide();
hideUrlElement();
removePreviewLegend();
}
function _previewArticle (showHelp) {
Evernote.Logger.debug("Start previewing article element");
if (previewElement)
{
var selectionFrame;
if (typeof Evernote.pageInfo !== undefined) {
selectionFrame = Evernote.pageInfo.getSelectionFrame();
}
Evernote.Logger.debug("Selection frame selected " + selectionFrame);
if (selectionFrame) {
var rect = {
width: selectionFrame.width,
height: selectionFrame.height,
top: selectionFrame.offsetTop,
bottom: (selectionFrame.height + selectionFrame.offsetTop),
left: selectionFrame.offsetLeft,
right: (selectionFrame.width + selectionFrame.offsetLeft)
};
Evernote.Logger.debug("contentVeil.revealStaticRect " + rect);
contentVeil.revealStaticRect(contentVeil.expandRect(rect, -9), true);
Evernote.Logger.debug("contentVeil.show ");
contentVeil.show();
}
else {
Evernote.Logger.debug("contentVeil.outlineElement");
contentVeil.outlineElement(previewElement, true);
}
if (showHelp) {
Evernote.Logger.debug("showPreviewLegend");
showPreviewLegend();
Evernote.Logger.debug("setTimeout:hidePreviewLegend");
setTimeout(hidePreviewLegend, 6000);
}
}
else {
Evernote.Logger.warn("Couldn't find a preview element. We should switch to 'full page' mode.");
}
}
/**
* Finds and preview article element.
* If reloadArticle is specified and equals to true, then discard previously found article and re-start search of article again.
* Otherwise use article found on previous call (if this is the first call then article will be searched anyway).
* @param reloadArticle
*/
function previewArticle (reloadArticle) {
var showHelp = Evernote.Options.articleSelection == Evernote.ArticleSelectionOptions.ENABLED;
clear();
previewElement = null;
if(reloadArticle) {
article = null;
}
Evernote.Logger.debug("Evernote.pageinfo " + Evernote.pageInfo);
if (typeof Evernote.pageInfo !== undefined) {
if(!article) {
previewElement = Evernote.pageInfo.getDefaultArticle(function(el){
Evernote.Logger.debug("Article element " + el.nodeName);
previewElement = el;
article = el;
Evernote.Logger.debug("Preview article ");
_previewArticle(showHelp);
});
article = previewElement;
} else {
previewElement = article;
_previewArticle(showHelp);
}
}
else {
Evernote.Logger.warn("Couldn't find a 'pageInfo' object.");
}
}
// When nudging the preview around the page, we want to skip nodes that aren't interesting. This includes empty
// nodes, containers that have identical contents to the already selected node, invisible nodes, etc.
// @TODO: There's a lot more we could probably add here.
function looksInteresting(candidate, given) {
if (!candidate) {
Evernote.Logger.warn("Can't determine if 'null' is interesting (it's probably not).");
return false;
}
// This is the parent of our 'HTML' tag, but has no tag itself. There's no reason it's ever more interesting than
// the HTML element.
if (candidate === window.document) {
return false;
}
//Disable clip of evernote main popup
if(Evernote.JQuery(candidate).closest("#evernote-content").length != 0) {
return false;
}
// We don't want to clip the clipper controls notification.
// @TODO: Probably want something similar for the content veil.
if (candidate === previewLegend) {
return false;
}
// Elements with neither text nor images are not interesting.
if (!candidate.textContent && (candidate.getElementsByTagName("img").length === 0)) {
return false;
}
// Elements with 0 area are not interesting.
var rect = Evernote.ElementExtension.getBoundingClientRect(candidate);
if (!rect.width || !rect.height) {
return false;
}
// Invisible elements are not interesting.
var style = Evernote.ElementExtension.getComputedStyle(candidate);
if ((style.visibility === "hidden") || (style.display === "none")) {
return false;
}
// If the nodes have a parent/child relationship, then they're only interesting if their visible contents differ.
if (candidate.parentNode && given.parentNode) {
if ((candidate.parentNode == given) || (given.parentNode == candidate)) {
if ((candidate.textContent === given.textContent) &&
(candidate.getElementsByTagName("img").length === given.getElementsByTagName("img").length)) {
return false;
}
}
}
return true;
}
// Returns the current article element, which may not be the same as the auto-detected one if the user has 'nudged'
// the selection around the page.
function getArticleElement() {
return previewElement;
}
function nudgePreview(direction) {
Evernote.Logger.debug("nudgePreview start");
if (!previewElement) {
return;
}
var oldPreview = previewElement;
Evernote.Logger.debug("nudgePreview: direction is " + direction);
Evernote.Logger.debug("nudgePreview: previewElement is " + previewElement.nodeName);
switch (direction) {
case "up":
var temp = previewElement.parentNode;
while (temp) {
if (looksInteresting(temp, previewElement)) {
// If we move up and then down, we want to move back to where we started, not the first child.
temp.enNudgeDescendToNode = previewElement;
previewElement = temp;
break;
}
temp = temp.parentNode;
}
break;
case "down":
Evernote.Logger.debug("nudgePreview: previewElement.enNudgeDescendToNode is " + previewElement.enNudgeDescendToNode);
if (previewElement.enNudgeDescendToNode)
{
var temp = previewElement.enNudgeDescendToNode;
// @TODO: make sure we clean these up somewhere else if we never reverse our nudging.
try {
delete previewElement.enNudgeDescendToNode;
} catch(e) {
previewElement.enNudgeDescendToNode = undefined;
}
previewElement = temp;
break;
}
Evernote.Logger.debug("nudgePreview: previewElement.children.length = " + previewElement.children.length);
for (var i = 0; i < previewElement.children.length; i++) {
Evernote.Logger.debug("nudgePreview: checking child is " + previewElement.children[i].nodeName);
if (looksInteresting(previewElement.children[i], previewElement)) {
Evernote.Logger.debug("nudgePreview: found interesting child" + previewElement.children[i]);
previewElement = previewElement.children[i];
break;
}
}
break;
case "left":
var temp = previewElement.previousElementSibling;
while (temp) {
if (looksInteresting(temp, previewElement)) {
previewElement = temp;
break;
}
temp = temp.previousElementSibling;
}
break;
case "right":
var temp = previewElement.nextElementSibling;
while (temp) {
if (looksInteresting(temp, previewElement)) {
previewElement = temp;
break;
}
temp = temp.nextElementSibling;
}
break;
default:
Evernote.Logger.warn("Unhandled nudge direction: " + direction);
}
// Drawing is expensive so don't bother if nothing changed.
if (oldPreview !== previewElement) {
Evernote.Logger.debug("nudgePreview: draw new element.");
contentVeil.outlineElement(previewElement, true);
}
}
function previewFullPage() {
var borderWidth = 10;
var w = Evernote.Utils.innerWidth();
var h = Evernote.Utils.innerHeight();
var rect = {
bottom: (h - borderWidth),
top: (borderWidth),
left: (borderWidth),
right: (w - borderWidth),
width: (w - (2 * borderWidth)),
height: (h - (2 * borderWidth))
}
clear();
contentVeil.reset();
contentVeil.revealStaticRect(rect, true);
contentVeil.show();
contentVeil.hideAllActiveObjects();
}
// Creates the union of two rectangles, which is defined to be the smallest rectangle that contains both given
// rectangles.
function unionRectangles(rect1, rect2) {
var rect = {
top: (Math.min(rect1.top, rect2.top)),
bottom: (Math.max(rect1.bottom, rect2.bottom)),
left: (Math.min(rect1.left, rect2.left)),
right: (Math.max(rect1.right, rect2.right))
}
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
return rect;
}
// Returns true if the rectangles match, false otherwise.
function rectanglesEqual(rect1, rect2) {
if (!rect1 && !rect2) return true;
if (!rect1) return false;
if (!rect2) return false;
if (rect1.top != rect2.top) return false;
if (rect1.bottom != rect2.bottom) return false;
if (rect1.left != rect2.left) return false;
if (rect1.right != rect2.right) return false;
if (rect1.width != rect2.width) return false;
if (rect1.height != rect2.height) return false;
return true;
}
// If the user triple-clicks a paragraph, we will often get a selection that includes the next paragraph after the
// selected one, but only up to offset 0 in that paragraph. This causes the built in getBoundingClientRect to give a
// box that includes the whole trailing paragraph, even though none of it is actually selected. Instead, we'll build
// our own bounding rectangle that omits the trailing box.
// @TODO: Currently this computes a box that is *too big* if you pass it a range that doesn't have start and/or end
// offsets that are 0, because it will select the entire beginning and ending node, instead of jsut the selected
// portion.
function computeAlternateBoundingBox(range) {
// If the end of selection isn't at offset 0 into an element node (rather than a text node), then we just return the
// original matching rectangle.
if ((range.endOffset !== 0) ||
(range.endContainer && range.endContainer.nodeType !== Evernote.Node.ELEMENT_NODE) ||
( range.startContainer && range.startContainer && range.startContainer.getBoundingClientRect) ||
( range.endContainer && range.endContainer.getBoundingClientRect) ||
( range.commonAncestorContainer && range.commonAncestorContainer.getBoundingClientRect)
) {
var rect = Evernote.ElementExtension.getBoundingClientRect(range);
if(rect.top == 0 && rect.bottom == 0 && rect.left == 0 && rect.right == 0) {
if(range.commonAncestorContainer && range.commonAncestorContainer.getBoundingClientRect) {
rect = range.commonAncestorContainer.getBoundingClientRect();
} else if(range.startContainer && range.startContainer.getBoundingClientRect) {
rect = range.startContainer.getBoundingClientRect();
} else if(range.endContainer && range.endContainer.getBoundingClientRect) {
rect = range.endContainer.getBoundingClientRect();
}
}
var mutableRect = {
top: rect.top,
bottom: rect.bottom,
left: rect.left,
right: rect.right,
width: rect.width,
height: rect.height
};
return mutableRect;
}
// This is the one we don't want.
var endElementRect = null;
try {
endElementRect = Evernote.ElementExtension.getBoundingClientRect(range.endContainer);
}
catch(ex) {
Evernote.Logger.warn("Couldn't get a bounding client rect for our end element, maybe it's a text node.");
}
// We look for a rectangle matching our end element, and if we find it, we don't copy it to our list to keep.
// You'd think we could just grab the last element in range.getClientRects() here and trim that one, which might be
// true, but the spec makes no claim that these are returned in order, so I don't want to rely on that.
// We keep track if we remove a rectangle, as we're only trying to remove one for the trailnig element. If there are
// more than one matching rectangle, we want to keep all but one of them.
var foundEnd = false;
var keptRects = [];
var initialRects = range.getClientRects();
for (var i = 0; i < initialRects.length; i++) {
if (rectanglesEqual(endElementRect, initialRects[i]) && !foundEnd) {
foundEnd = true;
}
else {
keptRects.push(initialRects[i]);
}
}
// Now compute our new bounding box and return that.
if (keptRects.length == 0) return Evernote.ElementExtension.getBoundingClientRect(range);
if (keptRects.length == 1) return keptRects[0];
var rect = keptRects[0];
for (var i = 1; i < keptRects.length; i++) {
rect = unionRectangles(rect, keptRects[i]);
}
return rect;
}
function applyElementRect(element, rect) {
var newRect = rect;
var tempRect = Evernote.ElementExtension.getBoundingClientRect(element);
// We skip anything with an area of one px or less. This is anything that has "display: none", or single pixel
// images for loading ads and analytics and stuff. Most hidden items end up at 0:0 and will stretch our rectangle
// to the top left corner of the screen if we include them. Sometimes single pixels are deliberately placed off
// screen.
if ((tempRect.width * tempRect.height) > 1) {
newRect = unionRectangles(Evernote.ElementExtension.getBoundingClientRect(element), rect);
}
if (element.children) {
for (var i = 0; i < element.children.length; i++) {
newRect = applyElementRect(element.children[i], newRect);
}
}
return newRect;
}
// In the case of positioned elements, a bounding box around an element doesn't necessarily contain its child
// elements, so we have this method to combine all of these into one bigger box. ContentVeil calls this function.
function computeDescendantBoundingBox(element) {
if (!element) return {top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0};
return applyElementRect(element, Evernote.ElementExtension.getBoundingClientRect(element));
}
function previewSelection(sel) {
var selection;
var selectionFrame;
if(sel) {
selection = sel;
}
else if (typeof Evernote.pageInfo !== undefined) {
selection = Evernote.pageInfo.getSelection();
// If our selection is in a frame or iframe, we'll compute an offset relative to that, so we need to adjust it by
// the offset of the frame.
selectionFrame = Evernote.pageInfo.getSelectionFrame();
}
contentVeil.reset();
var frameRect = null;
if (selectionFrame) {
frameRect = Evernote.ElementExtension.getBoundingClientRect(selectionFrame);
}
var range, rect, i;
// If !selection, then something has gone awry.
if (selection) {
clear();
contentVeil.reset();
// We attempt to highlight each selection, but this hasn't been tested for more than a single selection.
for (i = 0; i < Evernote.Utils.Selection.getRangeCount(selection); i++) {
range = Evernote.Utils.Selection.getRangeAt(selection, i);
rect = computeAlternateBoundingBox(Evernote.Utils.fixIERangeObject(range));
// Actual adjustment mentioned earlier regarding frames.
if (frameRect) {
rect.left += frameRect.left;
rect.right += frameRect.left;
rect.top += frameRect.top;
rect.bottom += frameRect.top;
}
contentVeil.revealRect(rect, true);
contentVeil.scrollToRect(rect);
}
}
contentVeil.show();
contentVeil.hideAllActiveObjects();
}
// Public API:
this.getArticleElement = getArticleElement;
this.looksInteresting = looksInteresting;
this.computeDescendantBoundingBox = computeDescendantBoundingBox;
this.previewArticle = previewArticle;
this.previewFullPage = previewFullPage;
this.previewSelection = previewSelection;
this.previewUrl = previewUrl;
this.clear = clear;
this.previewNudge = nudgePreview;
this.showOverlay = showOverlay;
}</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ElementExtension = {
querySelector : function(selector, doc) {
if(!doc) {
doc = document;
}
if(doc.querySelector) {
return doc.querySelector(selector);
}
else {
var head = doc.documentElement.firstChild;
var styleTag = doc.createElement("STYLE");
head.appendChild(styleTag);
doc.__qsResult = [];
styleTag.styleSheet.cssText = selector + "{x:expression(document.__qsResult.push(this))}";
window.scrollBy(0, 0);
head.removeChild(styleTag);
var result = [];
for (var i in doc.__qsResult)
result.push(doc.__qsResult[i]);
return result;
}
},
getComputedStyle : function(element, pseudoElement, win) {
var pseudo = pseudoElement;
var target = win;
if(!target)
target = window;
if(!pseudo) {
pseudo = null;
}
if(target.getComputedStyle)
return target.getComputedStyle(element, pseudo);
if(element.currentStyle) {
try {
var fixedElement = Evernote.Utils.cloneObject(element.currentStyle);
fixedElement['fontSize'] = Evernote.Utils.getIEComputedStyle(element, 'fontSize');
return fixedElement;
}
catch (err) {
return element.currentStyle;
}
}
return null;
},
hasParentNode : function(element) {
return element.parentNode && element.parentNode.nodeType != 9 && element.parentNode.nodeType != 11;
},
getBoundingClientRect : function(element) {
if(element && element.getBoundingClientRect) {
var rect = element.getBoundingClientRect();
var width = rect.width || element.offsetWidth || element.boundingWidth;
var height = rect.height || element.offsetHeight || element.boundingHeight;
return {
left : rect.left,
right : rect.right,
top : rect.top,
bottom : rect.bottom,
width : width,
height : height
}
}
return null;
},
hasAttribute : function(node, attrName) {
if(node) {
if(node.hasAttribute) {
return node.hasAttribute(attrName);
}
if(node.attributes) {
var attrValue = node.attributes[attrName];
return typeof attrValue != typeof undefined;
}
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ArrayExtension = {
indexOf : function(element, searchStr) {
if(!element) {
return -1;
}
if (element.indexOf)
return element.indexOf(searchStr);
for(var i = 0; i < element.length; i++) {
if(element[i] == searchStr)
return i;
}
return -1;
},
remove : function(arr, element) {
var elementPosition = Evernote.ArrayExtension.indexOf(arr, element);
if(elementPosition != -1) {
var rest = arr.slice(elementPosition + 1 || arr.length);
arr.length = elementPosition;
return arr.push.apply(arr, rest);
}
},
filter : function(arr, fun) {
var len = arr.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in arr) {
var val = arr[i];
if (fun.call(thisp, val, i, arr))
{
res.push(val);
}
}
}
return res;
}
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.StyleElementExtension = {
getPropertyValue : function(styleObj, propertyName) {
var props = propertyName;
if(!(props instanceof Array)) {
props = [propertyName];
}
Evernote.Logger.debug("Evernote.StyleElementExtension.getPropertyValue: number of properties to check " + props.length);
for(var i = 0; i < props.length; i++) {
var propName = props[i];
Evernote.Logger.debug("Evernote.StyleElementExtension.getPropertyValue: property name is " + propName);
var val;
if(styleObj.getPropertyValue) {
val = styleObj.getPropertyValue(propName);
Evernote.Logger.debug("Evernote.StyleElementExtension.getPropertyValue: value from getPropertyValue is " + val);
if(val)
return val;
}
val = styleObj[propName];
Evernote.Logger.debug("Evernote.StyleElementExtension.getPropertyValue: value from styleObj " + val);
if(val)
return val;
}
}
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.GlobalUtils = {};
(function(){
var urlMatcher = /^(.*?):\/\/((www\.)?(.*?))(:\d+)?(\/.*?)(\?.*)?$/;
var BAD_FAV_ICON_URLS = {"http://localhost/favicon.ico": true};
Evernote.GlobalUtils.componentizeUrl = function(url) {
var data = {
protocol: null,
domain: null,
domainNoWww: null,
port: null,
path: null,
queryString: null
};
var matches = urlMatcher.exec(url);
data.protocol = matches[1];
data.domain = matches[2];
data.domainNoWww = matches[4];
data.port = matches[5];
data.path = matches[6];
data.queryString = matches[7];
return data;
};
Evernote.GlobalUtils.getMessageCode = function(messageConst) {
Evernote.Logger.debug("getMessageCode: " + messageConst);
return Evernote.Messages[messageConst];
};
Evernote.GlobalUtils.absolutizeImages = function(element, path) {
if(path) {
Evernote.Utils.changeBackgroundImage(element, Evernote.Addin.getPath("resources") + path);
}
else if(element.attributes && element.attributes["background-image"]) {
Evernote.Utils.changeBackgroundImage(element, Evernote.Addin.getPath("resources") + element.attributes["background-image"].value);
}
Evernote.Logger.debug("absolutizeImages: walk through children");
for (var i = 0; i < element.children.length; i++) {
Evernote.GlobalUtils.absolutizeImages(element.children[i]);
}
Evernote.Logger.debug("absolutizeImages: end");
};
Evernote.GlobalUtils.localize = function(element) {
Evernote.Logger.debug("localize: Before lowercase");
Evernote.Logger.debug("localize: element " + element);
Evernote.Logger.debug("localize: element.nodeName " + element.nodeName);
var node = element.nodeName.toLowerCase();
Evernote.Logger.debug("localize: after lowercase");
if (node == "input" || node == "textarea") {
var type = element.type;
if (node == "textarea") type = "textarea";
switch (element.type) {
case "text":
case "textarea":
case "button":
case "submit":
case "search":
if (element.attributes && element.attributes["placeholder"]) {
var localizedMessage = Evernote.Addin.getLocalizedMessage(Evernote.GlobalUtils.getMessageCode(element.attributes["placeholder"].value));
Evernote.Logger.debug("localizedMessage is " + localizedMessage);
if (localizedMessage) {
try {
element.attributes["placeholder"].value = localizedMessage;
} catch(e) {
var placeHolderAttr = document.createAttribute("placeholder");
placeHolderAttr.nodeValue = localizedMessage;
element.setAttribute("placeholder", localizedMessage);
}
}
}
if (element.attributes && element.attributes["message"]) {
var localizedMessage = Evernote.Addin.getLocalizedMessage(Evernote.GlobalUtils.getMessageCode(element.attributes["message"].value));
Evernote.Logger.debug("localizedMessage is " + localizedMessage);
if (localizedMessage) {
element.value = localizedMessage;
}
}
break;
// unlocalizable.
case "checkbox":
case "password":
case "hidden":
break;
default:
throw new Error("We need to localize the value of input elements.");
}
}
else if (element.attributes && element.attributes["message"]) {
var localizedMessage = Evernote.Addin.getLocalizedMessage(Evernote.GlobalUtils.getMessageCode(element.attributes["message"].value));
if (localizedMessage) {
element.innerHTML = localizedMessage;
}
}
if (element.title){
var localizedTitle = Evernote.Addin.getLocalizedMessage(Evernote.GlobalUtils.getMessageCode(element.title));
if (localizedTitle) {
element.title = localizedTitle;
}
}
for (var i = 0; i < element.children.length; i++) {
Evernote.GlobalUtils.localize(element.children[i]);
}
};
Evernote.GlobalUtils.getQueryParams = function(url) {
var data = Evernote.GlobalUtils.componentizeUrl(url);
var queryString = data.queryString;
var params = {};
if (!queryString) {
return params;
};
queryString = queryString.substr(1); // Don't want the question mark.
queryString = queryString.split("#")[0]; // Get rid of any fragment identifier.
var pairs = queryString.split("&");
var i;
for (i = 0; i < pairs.length; i++) {
var item = pairs[i].split("=");
if (item[1]) {
item[1] = item[1].replace(/\+/g, " ");
}
params[item[0].toLowerCase()] = item[1];
}
return params;
};
Evernote.GlobalUtils.escapeXML = function(str) {
var map = {
"&" : "&",
"<" : "<",
">" : ">",
"\"" : """,
"'" : "'"
};
var a = str.split("");
for (var i = 0; i < a.length; i++) {
if (map[a[i]]) {
a[i] = map[a[i]];
}
}
return a.join("");
};
Evernote.GlobalUtils.createUrlClipContentForOldClipper = function(title, url) {
var style = "font-size: 12pt; line-height: 18px; display: inline;";
var content = "<a title=\"" + title + "\" style=\"" + style + "\" href=\"" + url + "\">" + url + "</a>";
var imgStyle = "display:inline;border: none; width: 16px; height: 16px; padding: 0px; margin: 0px 8px -2px 0px;";
return "<span><img title=\"" + title + "\" style=\"" + imgStyle + "\" src=\"" + Evernote.GlobalUtils.getFaviconImageUrlForOldClipper(url) +"\"/>" +
content + "</span>";
};
Evernote.GlobalUtils.getFaviconImageUrlForOldClipper = function(url) {
var re = new RegExp( "^[^:]+:\/+([^\/" + ":" + "]+).*$" );
var domain = url.replace( re, "$1" );
return "http://www.google.com/s2/favicons?domain=" + domain.toLowerCase();
};
Evernote.GlobalUtils.createUrlClipContent = function(title, url, favIcoUrl) {
var titleAttr = (title) ? Evernote.GlobalUtils.escapeXML(title) : "";
var style = "font-size: 12pt; line-height: 18px; display: inline;";
var content = "<a title=\"" + titleAttr + "\" style=\"" + style + "\" href=\"" + Evernote.GlobalUtils.escapeXML(url) + "\">" + Evernote.GlobalUtils.escapeXML(url) + "</a>";
if (favIcoUrl && !BAD_FAV_ICON_URLS[favIcoUrl.toLowerCase()]) {
var imgStyle = "display:inline;border: none; width: 16px; height: 16px; padding: 0px; margin: 0px 8px -2px 0px;";
content = "<span><img title=\"" + titleAttr + "\" style=\"" + imgStyle + "\" src=\"" + favIcoUrl + "\"/>" +
content + "</span>"
} else {
content = "<span>" + content + "</span>";
}
return content;
};
Evernote.GlobalUtils.executeOnDomReady = function(callback) {
Evernote.JQuery(document).ready(function() {
callback();
});
};
Evernote.GlobalUtils.isDocumentLoaded = function(doc) {
return doc.readyState == "complete" || doc.readyState == "interactive";
};
})();
</script><script charset="ANSI" defer="" type="text/javascript">/**
* Global utilities.
*/
Evernote.Utils = {
getIEComputedStyle : function(elem, prop) {
//Dean Edwards method. See first comment here: http://bit.ly/cMSs9R
var value = elem.currentStyle[prop] || 0
var leftCopy = elem.style.left
var runtimeLeftCopy = elem.runtimeStyle.left
elem.runtimeStyle.left = elem.currentStyle.left
elem.style.left = (prop === "fontSize") ? "1em" : value
value = elem.style.pixelLeft + "px";
elem.style.left = leftCopy
elem.runtimeStyle.left = runtimeLeftCopy
return value
},
cloneObject : function(obj){
if(obj == null || typeof(obj) != 'object')
return obj;
if(obj.constructor == Array)
return [].concat(obj);
var temp = {};
for(var key in obj)
temp[key] = this.cloneObject(obj[key]);
return temp;
},
saveSelection : function(win) {
Evernote.Logger.debug( "Utils.SaveSelection()" );
var selectionFinder = new Evernote.SelectionFinder(win.document);
selectionFinder.find( true );
if(selectionFinder.hasSelection()) {
return Evernote.Utils.cloneRange(selectionFinder.getRange());
}
return null;
},
clearSelection : function(doc) {
if(doc.getSelection) {
doc.getSelection().removeAllRanges();
}
},
/**
* Make selection of passed range in document.
* @param doc - DOM object
* @param range - selection range
*/
selectRange : function(doc, range) {
if(doc.getSelection) {
doc.getSelection().addRange(range);
}
else if (doc.selection && range) {
range.select();
}
},
/**
* Creates copy of selection range only if it supports it, otherwise returns same range
* @param range - Range object
* @return {Range}
*/
cloneRange : function(range) {
Evernote.Logger.debug("cloneRange: start");
if(range && range.cloneRange) {
return range.cloneRange();
}
if(range.duplicate) {
Evernote.Logger.debug("cloneRange: result = " + range.duplicate());
return range.duplicate();
}
return range;
},
/**
* Checks whether selection is presented.
* @param win - window object that should be checked.
* @return true - if selection is presented, false otherwise.
*/
hasSelection : function(win) {
Evernote.Logger.debug( "Utils.hasSelection()" );
var selectionFinder = new Evernote.SelectionFinder(win.document)
if ( selectionFinder.hasSelection() ) {
return true;
}
else {
selectionFinder.find( true );
return selectionFinder.hasSelection();
}
},
/**
* Gets favicon url from the document (if any)
* @param doc - document to inspect.
* @return url to the favicon or null.
*/
getFavIconUrl : function(doc) {
var links = doc.getElementsByTagName("link");
var i;
for (i = 0; i < links.length; i++) {
if (links[i].rel) {
var rels = links[i].rel.toLowerCase().split(/\s+/);
if (Evernote.ArrayExtension.indexOf(rels, "icon") !== -1) {
// Found it!
return links[i].href;
}
}
}
return null;
},
/**
* If passed string length is more than length argument, than string is trimmed to length and dots are added
* (total length of the returned string does not exceed specified length).
* @param str - string to trim
* @param length - max number of characters in the string
* @param addition - text to be added to truncated string
* @return {*}
*/
cutToLength : function(str, length, addition) {
if(!addition) {
addition = "...";
}
if(str.length > length) {
return (str.substring(0, length-3) + addition);
}
return str;
},
/**
* Change new line symbol to html <br/>
*/
newLineToBr : function(str) {
return str.replace(/(\r\n|\n|\r)/gm, "<br/>");
},
/**
* Encodes html specific characters (<, >, &, etc.) in specified string
* @param str - string to encode.
* @return new string with encoded characters.
*/
htmlEncode : function( str ) {
var result = "";
for ( var i = 0; i < str.length; i++ ) {
var charcode = str.charCodeAt( i );
var aChar = str[ i ];
if(!aChar) {
aChar = str.charAt(i);
}
if(charcode >= 55296 )
result += aChar;
else if ( charcode > 0x7f ) {
result += "&#" + charcode + ";";
}
else if ( aChar == '>' ) {
result += ">";
}
else if ( aChar == '<' ) {
result += "<";
}
else if ( aChar == '&' ) {
result += "&";
}
else {
result += str[ i ] ? str[ i ] : str.charAt(i);
}
}
return result;
},
/**
* Absolutize specified url by specified base.
* @param base - base url
* @param href - relative url (from base)
*/
makeAbsolutePath : function ( base, href ) {
function parseURI( url ) {
var m = String( url ).replace( /^\s+|\s+$/g, '' ).match( /^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/ );
// authority = '//' + user + ':' + pass '@' + hostname + ':' port
return (m ? {
href : m[ 0 ] || '',
protocol : m[ 1 ] || '',
authority : m[ 2 ] || '',
host : m[ 3 ] || '',
hostname : m[ 4 ] || '',
port : m[ 5 ] || '',
pathname : m[ 6 ] || '',
search : m[ 7 ] || '',
hash : m[ 8 ] || ''
} : null);
}
function absolutizeURI( base, href ) {// RFC 3986
function removeDotSegments( input ) {
var output = [];
input.replace( /^(\.\.?(\/|$))+/, '' )
.replace( /\/(\.(\/|$))+/g, '/' )
.replace( /\/\.\.$/, '/../' )
.replace( /\/?[^\/]*/g, function ( p ) {
if ( p === '/..' ) {
output.pop();
}
else {
output.push( p );
}
} );
return output.join( '' ).replace( /^\//, input.charAt( 0 ) === '/' ? '/' : '' );
}
href = parseURI( href || '' );
base = parseURI( base || '' );
return !href || !base ? null : (href.protocol || base.protocol) +
(href.protocol || href.authority ? href.authority : base.authority) +
removeDotSegments( href.protocol || href.authority || href.pathname.charAt( 0 ) === '/' ? href.pathname :
(href.pathname ? ((base.authority && !base.pathname ? '/' : '') +
base.pathname.slice( 0, base.pathname.lastIndexOf( '/' ) + 1 ) + href.pathname) : base.pathname) ) +
(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
href.hash;
}
return absolutizeURI( base, href );
},
getNestedDocuments : function( doc ) {
Evernote.Logger.debug( "Utils.getNestedDocuments()" );
var docs = [ ];
try {
var frames = ( doc ) ? doc.getElementsByTagName( "frame" ) : [ ];
for ( var i = 0; i < frames.length; ++i ) {
if ( frames[ i ].contentDocument ) {
docs.push( frames[ i ].contentDocument );
}
}
var iframes = ( doc ) ? doc.getElementsByTagName( "iframe" ) : [ ];
for ( i = 0; i < iframes.length; ++i ) {
if ( iframes[ i ].contentDocument ) {
docs.push( iframes[ i ].contentDocument );
}
}
} catch (e) {
Evernote.Logger.error("getNestedDocuments failed with error " + e);
}
Evernote.Logger.debug( "Utils.getNestedDocuments() end" );
return docs;
},
isSupportedUrl : function(url) {
return url.indexOf("http") == 0;
},
getFontSizeInPixels : function(elementFontSize) {
function computedStyle(element, property){
var s = false;
if(window.getComputedStyle){
s = window.getComputedStyle(element, null).getPropertyValue(property);
} else if(element.currentStyle){
var p = property.split('-');
var str = new String('');
for(var i = 0; i < p.length; i++){
str += (i > 0)?(p[i].substr(0, 1).toUpperCase() + p[i].substr(1)):p[i];
}
s = element.currentStyle[str];
}
return s;
}
function getPercentageSize(size) {
var currentFontSize = parseFloat(size);
var htmlFontSize = 16;
var htmlElement = document.getElementsByTagName("html");
if(htmlElement && htmlElement.length > 0) {
var htmlComputedFontSize = computedStyle(htmlElement[0], "font-size");
if(htmlComputedFontSize && htmlComputedFontSize.indexOf("%") == -1) {
htmlFontSize = Evernote.Utils.getFontSizeInPixels(htmlComputedFontSize);
}
}
return htmlFontSize * currentFontSize / 100;
}
var size = elementFontSize;
if(size.indexOf("em") > -1) {
var defFont = computedStyle(document.body, "font-size");
if(defFont.indexOf("pt") > -1){
defFont = Math.round(parseInt(defFont)*96/72);
} else if(defFont.indexOf("%") > -1) {
defFont = getPercentageSize(defFont);
} else{
defFont = parseInt(defFont);
}
size = Math.round(defFont * parseFloat(size));
}
else if(size.indexOf("pt") > -1){
size = Math.round(parseInt(size)*96/72)
} else if(size.indexOf("%") > -1) {
size = getPercentageSize(size);
}
return parseInt(size);
},
innerWidth : function() {
if(window.innerWidth)
return window.innerWidth;
var doc= (document.body.clientWidth)? document.body: document.documentElement;
return doc.clientWidth;
},
innerHeight : function() {
if(window.innerHeight)
return window.innerHeight;
var doc= (document.body.clientHeight)? document.body: document.documentElement;
return doc.clientHeight;
},
scrollTop : function() {
var doc = document.body.scrollTop ? document.body : document.documentElement;
return doc.scrollTop;
},
scrollLeft : function() {
var doc = document.body.scrollLeft ? document.body : document.documentElement;
return doc.scrollLeft;
},
/**
* Stopped propagation of keydown events for passed selector.
* @param selector - could be element or jquery selector.
*/
hardInput : function(selector) {
this.elem = Evernote.JQuery(selector);
this.elem.keydown(function(e) {
e.stopPropagation();
});
},
isQuirkMode : function() {
return document.compatMode == "BackCompat" && !Evernote.BrowserDetection.isIE11();
},
isInstanceOf : function(obj, type) {
if(obj && type) {
try {
return obj instanceof type;
} catch (e) {
return type.toString().indexOf(typeof obj) != -1;
}
}
return false;
},
changeBackgroundImage : function(element, localpath) {
if(element.style) {
element.style.backgroundImage = "url('file:///" + localpath.replace(/\\/g, "/").replace(/\s/g, "%20") + "')";
}
},
format: function(str) {
var args = arguments;
return str.replace(/\{(\d+)\}/g, function (m, n) { return args[(n | 0)+1]; });
},
fixIERangeObject : function(range,win) { //Only for IE8 and below.
win=win || window;
if(!range) return null;
if(!range.startContainer && win.document.selection) { //IE8 and below
var _findTextNode=function(parentElement,text) {
//Iterate through all the child text nodes and check for matches
//As we go through each text node keep removing the text value (substring) from the beginning of the text variable.
var container=null,offset=-1;
for(var node=parentElement.firstChild; node; node=node.nextSibling) {
if(node.nodeType==3) {//Text node
var find=node.nodeValue;
var pos=text.indexOf(find);
if(pos==0 && text!=find) { //text==find is a special case
text=text.substring(find.length);
} else {
container=node;
offset=text.length-1; //Offset to the last character of text. text[text.length-1] will give the last character.
break;
}
}
}
//Debug Message
//alert(container.nodeValue);
return {node: container,offset: offset}; //nodeInfo
};
var rangeCopy1=range.duplicate(), rangeCopy2=range.duplicate(); //Create a copy
var rangeObj1=range.duplicate(), rangeObj2=range.duplicate(); //More copies :P
rangeCopy1.collapse(true); //Go to beginning of the selection
rangeCopy1.moveEnd('character',1); //Select only the first character
rangeCopy2.collapse(false); //Go to the end of the selection
rangeCopy2.moveStart('character',-1); //Select only the last character
//Debug Message
// alert(rangeCopy1.text); //Should be the first character of the selection
var parentElement1=rangeCopy1.parentElement(), parentElement2=rangeCopy2.parentElement();
//If user clicks the input button without selecting text, then moveToElementText throws an error.
if(window.HTMLInputElement && (parentElement1 instanceof window.HTMLInputElement || parentElement2 instanceof HTMLInputElement)) {
return null;
}
rangeObj1.moveToElementText(parentElement1); //Select all text of parentElement
rangeObj1.setEndPoint('EndToEnd',rangeCopy1); //Set end point to the first character of the 'real' selection
rangeObj2.moveToElementText(parentElement2);
rangeObj2.setEndPoint('EndToEnd',rangeCopy2); //Set end point to the last character of the 'real' selection
var text1=rangeObj1.text; //Now we get all text from parentElement's first character upto the real selection's first character
var text2=rangeObj2.text; //Here we get all text from parentElement's first character upto the real selection's last character
var nodeInfo1=_findTextNode(parentElement1,text1);
var nodeInfo2=_findTextNode(parentElement2,text2);
//Finally we are here
range.startContainer=nodeInfo1.node;
range.startOffset=nodeInfo1.offset;
range.endContainer=nodeInfo2.node;
range.endOffset=nodeInfo2.offset+1; //End offset comes 1 position after the last character of selection.
}
return range;
},
fixedPosition : function(win, el, topOffset, immediate) {
function applyPosition(elem) {
if(elem) {
var scrollPosition = win.document.documentElement.scrollTop || win.document.body.scrollTop;
var offset;
if(typeof topOffset == "function") {
offset = topOffset();
} else {
offset = scrollPosition + topOffset;
}
elem.animate({top: offset}, 100);
}
}
if(el) {
var elem = Evernote.JQuery(el);
if(Evernote.Utils.isQuirkMode()) {
elem.css("position", "absolute");
if (win.attachEvent)
win.attachEvent("onscroll", function() {applyPosition(elem);});
else if (win.addEventListener)
win.addEventListener("scroll", function() {applyPosition(elem);}, false);
else
Evernote.Logger.error( "Utils.fixedPosition() can't attachEvent" );
if(immediate) {
applyPosition(elem);
}
}
}
},
mergeCustomComboBoxStrings : function(notebook, owner, ownedByStr, maxLen) {
var totalLen = notebook.length;
if (owner.length) {
// format: "space","(","<owned by localize string>","space","<owner>",")"
// magic number "4" is: "space","(","space",")"
totalLen += ownedByStr.length + owner + 4;
}
if (totalLen <= maxLen) {
return {
note: notebook,
own: "",
title: ""
};
}
var half = maxLen / 2 - 2;
if (owner.length == 0) {
return {
note: notebook.substr(0, half) + "..." + notebook.substring(notebook.length - half, notebook.length),
own: "",
title: notebook
};
}
var ownerFormatStr = "(" + ownedByStr + " " + owner + ")";
var title = notebook + ownerFormatStr;
var resultString = title.substr(0, half) + "..." + title.substr(title.length - half);
if (notebook.length <= half) {
return {
note: notebook,
own: "..." + title.substr(title.length - notebook.length),
title: notebook + " " + ownerFormatStr
};
}else if (ownerFormatStr <= half) {
return {
note: notebook.substr(0, maxLen - ownerFormatStr.length) + "...",
own: ownerFormatStr,
title: notebook + " " + ownerFormatStr
};
}else {
return {
note: resultString.substr(0, resultString.length - half),
own: resultString.substr(half + 3),
title: notebook + " " + ownerFormatStr
};
}
},
setEvernoteLogo : function(selector) {
var serverLocation = Evernote.Addin.getServerLocation();
Evernote.Logger.debug("Evernote server location is " + serverLocation);
if (serverLocation.length && serverLocation.indexOf("international") == -1) {
var evernoteLogoEl = Evernote.JQuery(selector);
if (evernoteLogoEl) {
var imageFileName = "images/web-clipper-logo_" + serverLocation + ".png";
this.changeBackgroundImage(evernoteLogoEl.get(0), Evernote.Addin.getPath("resources") + imageFileName);
}
}
},
Selection : {
getRangeCount : function(selection) {
if(selection.rangeCount) {
return selection.rangeCount;
}
return 1;
},
getRangeAt : function(selection, pos) {
if(selection.getRangeAt) {
selection.getRangeAt(pos);
}
return selection;
},
getCommonAncestorContainer : function(range) {
if(range.commonAncestorContainer) {
return range.commonAncestorContainer;
}
else if(range.parentElement) {
return range.parentElement();
}
return null;
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ClipperActions = {
CLIP_URL : "0",
CLIP_FULL_PAGE: "1",
CLIP_ARTICLE: "2",
CLIP_SELECTION: "3",
CLIP_IMAGE: "4"
};
Evernote.ArticleSelectionOptions = {
ENABLED : "0",
DISABLED : "1",
ENABLED_WITHOUT_HINTS : "2"
};
Evernote.Options = {
defaultAction : Evernote.ClipperActions.CLIP_ARTICLE,
articleSelection: Evernote.ArticleSelectionOptions.ENABLED,
selectedNotebookUid: -1,
/**
* Return string representation of the object (you can use it in load method to restore object from string).
*/
_serialize: function() {
return JSON.stringify(this);
},
load : function() {
var optionsContent = Evernote.FS.getFileContent(this._getOptionsFilePath());
this._load(optionsContent);
},
_getOptionsFilePath : function() {
return Evernote.Addin.getPath("options") + "options.json";
},
_load : function(str) {
if(str) {
var option = JSON.parse(str);
if(option) {
if(option.defaultAction) {
this.defaultAction = option.defaultAction;
}
if(option.articleSelection) {
this.articleSelection = option.articleSelection;
}
if(option.selectedNotebookUid) {
this.selectedNotebookUid = option.selectedNotebookUid;
}
}
}
},
setDefaultAction : function(action) {
this.defaultAction = action;
this.save();
},
setNotebook : function(notebookUid) {
this.selectedNotebookUid = notebookUid;
this.save();
},
setArticleSelection : function(articleSelection) {
this.articleSelection = articleSelection;
this.save();
},
save : function() {
Evernote.FS.writeToFile(this._getOptionsFilePath(), this._serialize());
}
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.BrowserDetection = {
isIE11 : function() {
return navigator.userAgent.indexOf("Trident/7.0") != -1
},
isIE10 : function() {
return navigator.userAgent.indexOf("MSIE 10") != -1;
},
isIE7 : function() {
return navigator.userAgent.indexOf("MSIE 7.0") != -1 && navigator.userAgent.indexOf("Trident/7.0") == -1;
},
isIE8 : function() {
return navigator.userAgent.indexOf("MSIE 8.0") != -1 && navigator.userAgent.indexOf("Trident/7.0") == -1;
},
isLessThanIE9 : function() {
return Evernote.BrowserDetection.isIE7() || Evernote.BrowserDetection.isIE8()
},
isIE10orGreater : function() {
return Evernote.BrowserDetection.isIE10() || Evernote.BrowserDetection.isIE11()
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Node = {
ELEMENT_NODE : 1,
TEXT_NODE : 3
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Messages = {
CLIP_ARTICLE : 117,
ENTER : 118,
CLIP_SELECTION: 113,
CLIP_URL: 115,
CLIP_FULL_PAGE : 116,
OPTIONS : 119,
DEFAULT_ACTION: 120,
ARTICLE_SELECTION: 121,
ENABLED: 122,
DISABLED: 123,
ENABLED_NO_HINTS: 124,
ARTICLE_SELECTION_HINT: 125,
EXPAND_SELECTION: 126,
SHRINK_SELECTION: 127,
MOVE_SELECTION: 128,
CLIP_ARTICLE_HINT: 129,
CLIPPING : 130,
UNSUPPORTED_SCHEMA : 131,
UNTITLED_NOTE : 132,
ADD_TAGS : 133,
ADD_COMMENTS : 134,
OWNED_BY: 135,
SHARED_NOTEBOOKS: 136,
BUSINESS_NOTEBOOKS: 137,
LOADING_TAGS: 140,
LOGIN_FAILED: 141,
CLOSE: 142,
LOADING_NOTEBOOKS: 146,
CLIP_FAILED_TITLE: 147,
VERSION: 148,
LIMIT_TAGS : 150
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ResponseReceiver = {
parsers : [],
receivers : [],
onResponse: function(str) {
Evernote.Logger.debug("Response received" + str);
for(var i in Evernote.ResponseReceiver.parsers) {
if(Evernote.ResponseReceiver.parsers[i].canParse && Evernote.ResponseReceiver.parsers[i].canParse(str)) {
Evernote.ResponseReceiver.notify(Evernote.ResponseReceiver.parsers[i].parse(str));
}
}
},
registerParser: function(parser) {
Evernote.ResponseReceiver.parsers.push(parser);
},
subscribe: function(receiver) {
Evernote.ResponseReceiver.receivers.push(receiver);
},
notify: function(data) {
for(var i=0; i < Evernote.ResponseReceiver.receivers.length; i++) {
Evernote.ResponseReceiver.receivers[i].onDataReceived(data);
}
}
};
function EvernoteGlobalReceiver(str) {
Evernote.ResponseReceiver.onResponse(str);
}
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ProcessIDResponseParser = {
parse : function(str) {
Evernote.Logger.debug("ProcessIDResponseParser: response" + str);
var xmlDom = Evernote.JQuery(str);
var result = xmlDom.attr("process_id");
return new Evernote.Response("process_id", result);
},
canParse: function(str) {
var request = Evernote.JQuery(str).attr("request");
return request && (request == "get_process_id");
}
};
Evernote.ResponseReceiver.registerParser(Evernote.ProcessIDResponseParser);</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ErrorResponseParser = {
parse : function(str) {
Evernote.Logger.warn("Received error " + str);
var error = Evernote.JQuery(str);
var errorCode = error.attr("code");
var errorMessage = null;
var problem = null;
if(error.length == 1) {
var problems = error.find("problem");
if(problems && problems.length > 0) {
problem = Evernote.JQuery(problems[0]);
}
}
else if(error.length > 2) {
errorMessage = error[2].toString();
}
if(problem) {
errorMessage = problem.text();
} else if(!errorMessage) {
errorMessage = error.attr("details");
}
switch (errorCode) {
case Evernote.ErrorCodes.AUTHENTICATION_ERROR :
errorMessage = Evernote.Addin.getLocalizedMessage(Evernote.Messages.LOGIN_FAILED);
break;
case Evernote.ErrorCodes.CLIP_ERROR :
errorMessage = Evernote.Addin.getLocalizedMessage(Evernote.Messages.CLIP_FAILED_TITLE) + "\n" + errorMessage;
}
var msg = {
message: errorMessage,
code: errorCode
};
return new Evernote.Response("error", msg);
},
canParse: function(str) {
var request = Evernote.JQuery(str).get(0);
return (request && (request.nodeName == "ERROR"));
}
};
Evernote.ResponseReceiver.registerParser(Evernote.ErrorResponseParser);</script><script charset="ANSI" defer="" type="text/javascript">Evernote.AlertErrorHandler = {
processError: function(error) {
alert(error.message);
return true;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ErrorHandler = {
getHandler: function() {
return [Evernote.Addin, Evernote.AlertErrorHandler, Evernote.evernotePopup];
},
onDataReceived : function(response) {
if(response.type) {
if(response.type == "error") {
this.notifyHandlers(response.data);
}
}
},
notifyHandlers : function(error) {
for(var i = 0; i < this.getHandler().length; i++) {
var handler = this.getHandler()[i];
if(handler && handler.processError && handler.processError(error)) {
return;
}
}
}
};
Evernote.ResponseReceiver.subscribe(Evernote.ErrorHandler);</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Response = function(type, data) {
this.data = data;
this.type = type;
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.FS = {
_addon : null,
init : function(addon) {
this._addon = addon;
},
/**
* Write content to the specified path.
* @param path - file path.
* @param content - content, that should be written to
*/
writeToFile : function(path, content) {
if (!this._addon)
return;
try {
this._addon.WriteFileContent( path, content );
} catch (e) {
Evernote.Logger.error( "FS.WriteFileContent() failed " + e );
}
},
/**
* Read content of the file specified by path.
* @param path - file path.
* @return {string} - content of the file
*/
getFileContent : function(path) {
if (!this._addon)
return null;
try {
return this._addon.ReadFileContent( path );
} catch (e) {
Evernote.Logger.error( "FS.ReadFileContent() failed " + e );
}
return null;
}
};
</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.AbstractElementSerializer = function AbstractElementSerializer( node, nodeStyle ) {
this.initialize( node, nodeStyle );
};
Evernote.AbstractElementSerializer.isResponsibleFor = function( /*navigator*/ ) {
return false;
};
Evernote.AbstractElementSerializer.prototype._node = null;
Evernote.AbstractElementSerializer.prototype._nodeStyle = null;
Evernote.AbstractElementSerializer.prototype.handleInheritance = function( child/*, parent */) {
Evernote.ElementSerializerFactory.ClassRegistry.push( child );
};
Evernote.AbstractElementSerializer.prototype.initialize = function( node, nodeStyle ) {
this._node = node;
this._nodeStyle = nodeStyle;
};
Evernote.AbstractElementSerializer.prototype.serialize = function( /*docBase*/ ) {
return "";
};
Evernote.AbstractElementSerializer.prototype.getImageUrl = function() {
return "";
};</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.ElementSerializerFactory = {
getImplementationFor : function( node ) {
for ( var i = 0; i < this.ClassRegistry.length; ++i ) {
if ( this.ClassRegistry[ i ].isResponsibleFor( node ) ) {
return this.ClassRegistry[ i ];
}
}
return null;
}
};
Evernote.ElementSerializerFactory.ClassRegistry = [ ];</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.ClipStylingStrategy = function ClipStylingStrategy( ) {
this.initialize( );
};
Evernote.ClipStylingStrategy.prototype.initialize = function( ) {
};
Evernote.ClipStylingStrategy.prototype.styleForNode = function( /*node, root, fullPage, clipStyleType*/ ) {
return null;
};
Evernote.ClipStylingStrategy.prototype.getNodeView = function ( node ) {
var doc = node.ownerDocument;
return (doc.defaultView) ? doc.defaultView : null;
};
Evernote.ClipStylingStrategy.prototype.getNodeStyle = function( node, filterFn, pseudo ) {
Evernote.Logger.debug( "ClipStylingStrategy.getNodeStyle()" );
var style = new Evernote.ClipStyle();
if ( pseudo != "" ) {
return style;
}
if ( node && typeof node.nodeType == 'number' && node.nodeType == 1 ) {
var view = this.getNodeView( node );
style = new Evernote.ClipStyle( Evernote.ElementExtension.getComputedStyle( node, null, view ), filterFn );
}
return style;
};
Evernote.ClipStyleType = {
NodeStyle : 0x01,
InheritedFontStyle: 0x02,
InheritedBgStyle: 0x04,
AllStyle : 0x01 | 0x02 | 0x04,
Default : 0x01 | 0x02
};</script><script charset="ANSI" defer="" type="text/javascript">
Evernote.ClipFullStylingStrategy = function ClipFullStylingStrategy( ) {
this.initialize( );
};
Evernote.inherit( Evernote.ClipFullStylingStrategy, Evernote.ClipStylingStrategy, true );
Evernote.ClipFullStylingStrategy.prototype.styleForNode = function ( node, root, fullPage, clipStyleType ) {
Evernote.Logger.debug( "ClipStylingStrategy.styleForNode()" );
if ( clipStyleType == null ) {
clipStyleType = Evernote.ClipStyleType.Default;
}
var bodyStyles = new Evernote.ClipStyle( [ ], function ( prop, value ) {
return value != ""
} );
var inhFontStyles = new Evernote.ClipStyle( [ ] );
var inhBgStyles = [ ];
if ( (clipStyleType & Evernote.ClipStyleType.NodeStyle) == Evernote.ClipStyleType.NodeStyle ) {
Evernote.Logger.debug( "ClipStylingStrategy.styleForNode(): get node style" );
try {
if ( node.nodeName.toLowerCase() == "body" ) {
for ( var attrName in Evernote.ClipStyle.STYLE_ATTRIBUTES ) {
if ( Evernote.ElementExtension.hasAttribute(node, attrName) ) {
var cssPropName = Evernote.ClipStyle.STYLE_ATTRIBUTES[ attrName ];
var style = { };
style[ cssPropName ] = node.getAttribute( attrName );
bodyStyles.addStyle( style );
}
}
}
} catch(e) {
Evernote.Logger.error("ClipFullStylingStrategy.styleForNode failed to get attributes from body due to error " + e);
}
var evaluatedStyles = this.getNodeStyle( node );
if ( node.nodeName.toLowerCase() == "table" && !evaluatedStyles.getStyle( "font-size" ) ) {
evaluatedStyles.addStyle( {"font-size":"1em"} );
}
if ( node.nodeName.toLowerCase() == "img" ) {
style = new Evernote.ClipStyle( Evernote.ElementExtension.getComputedStyle( node, null, this.getNodeView( node ) ), function ( prop, value ) {
return value != ""
} );
evaluatedStyles.addStyle( { height:style.getStyle( "height" ) } );
evaluatedStyles.addStyle( { width:style.getStyle( "width" ) } );
}
if ( evaluatedStyles.getStyle( "background-image" ) ) {
var regExp = /url\((.*?)\)/;
evaluatedStyles.addStyle( { "background-image": Evernote.StyleElementExtension.getPropertyValue(Evernote.ElementExtension.getComputedStyle( node, null, this.getNodeView( node ) ), Evernote.IEStylePropertiesMapping.getPropertyNameFor("background-image") ).replace( regExp, "url('$1')").replace(/('")|("')|('')/g, "'")} );
}
if ( evaluatedStyles.getStyle( "height" ) == "100%" && Evernote.StyleElementExtension.getPropertyValue(Evernote.ElementExtension.getComputedStyle( node, null, this.getNodeView( node ) ), "height" ) == "0px" ) {
evaluatedStyles.addStyle( { height:"0px" } );
}
bodyStyles.mergeStyle( evaluatedStyles, true );
}
if ( node == root && !fullPage ) {
if ( (clipStyleType & Evernote.ClipStyleType.InheritedFontStyle) == Evernote.ClipStyleType.InheritedFontStyle ) {
Evernote.Logger.debug( "ClipStylingStrategy.styleForNode(): get inherited font style" );
inhFontStyles = this.inheritFontForNode( node, true );
Evernote.Logger.debug( "ClipStylingStrategy.styleForNode(): inherited fonts " );
}
if ( (clipStyleType & Evernote.ClipStyleType.InheritedBgStyle) == Evernote.ClipStyleType.InheritedBgStyle ) {
Evernote.Logger.debug( "ClipStylingStrategy.styleForNode(): get inherited bg style" );
inhBgStyles = this.inheritBackgroundForNode( node, true );
}
}
bodyStyles.mergeStyle( inhFontStyles, true );
return {
nodeStyle:bodyStyles,
inheritedFonts:inhFontStyles,
inheritedBackground:inhBgStyles,
evaluated:bodyStyles
};
};
Evernote.ClipFullStylingStrategy.prototype.getNodeStyle = function ( node, filterFn, pseudo ) {
Evernote.Logger.debug( "ClipStylingStrategy.getNodeStyle()" );
if ( pseudo == null || typeof pseudo == "undefined" ) {
pseudo = "";
}
var style = new Evernote.ClipStyle([ ], filterFn);
Evernote.Logger.debug( "Pseudo : " + pseudo );
if ( pseudo == "" && node && typeof node.nodeType == 'number' && node.nodeType == 1 ) {
var view = this.getNodeView( node );
style = new Evernote.ClipStyle( Evernote.ElementExtension.getComputedStyle( node, null, view ), filterFn );
}
return style;
};
Evernote.ClipFullStylingStrategy.prototype.inheritFontForNode = function ( node, recur ) {
Evernote.Logger.debug( "ClipFullStylingStrategy.inheritFontForNode()" );
var fontStyle = new Evernote.ClipStyle();
if ( !node ) {
return fontStyle;
}
var parent = node;
var styles = [ ];
var nodes = [ ];
var dynamicUnit = ["%", "em"];
var sizeUnitRegExp = /(.*?)(em|%|px|pt)/;
while ( parent ) {
nodes.push( parent );
styles.push( new Evernote.ClipStyle( this.getNodeStyle( parent ), function ( prop, value ) {
return (Evernote.ArrayExtension.indexOf(Evernote.ClipStyle.INHERITED_STYLES, prop ) > 0 && value != "inherit" );
} ) );
Evernote.Logger.debug( "Inh parent style:" + styles[styles.length - 1].toString() );
if ( !recur || parent == document.body ) {
break;
}
else {
parent = parent.parentElement;
}
}
//merge styles starting from low-priority parent styles
Evernote.Logger.debug( "Styles inh for processing:" + (styles.length - 1) );
for ( var i = styles.length - 1; i >= 0; i-- ) {
var style = styles[ i ];
var fontSize = fontStyle.getStyle( "font-size" );
var overFontStyle = style.getStyle( "font-size" );
Evernote.Logger.debug( "fontSize:" + fontSize + " ;overFontStyle: " + overFontStyle );
if ( fontSize && overFontStyle ) {
var resFontSize = fontSize.match( sizeUnitRegExp );
if ( resFontSize == null ) {
continue;
}
var sizeVal = resFontSize[1];
var sizeUnit = resFontSize[2];
var resOverFontSize = overFontStyle.match( sizeUnitRegExp );
if ( resOverFontSize == null ) {
continue;
}
var overSizeVal = resOverFontSize[1];
var overSizeUnit = resOverFontSize[2];
if ( Evernote.ArrayExtension.indexOf(dynamicUnit, overSizeUnit ) != -1 ) {
if ( overSizeUnit == "%" ) {
style.addStyle( { "font-size":(parseFloat( sizeVal ) * parseFloat( overSizeVal ) / 100).toString() + sizeUnit } );
}
else {
style.addStyle( { "font-size":(parseFloat( sizeVal ) * parseFloat( overSizeVal )).toString() + ((sizeUnit != "em") ? sizeUnit : overSizeUnit) } );
}
}
Evernote.Logger.debug( "Style: " + i + " ;Eval inh style:" + style.toString() );
}
fontStyle.mergeStyle( style, true );
}
return fontStyle;
};
Evernote.ClipFullStylingStrategy.prototype.inheritBackgroundForNode = function ( node, recur ) {
Evernote.Logger.debug( "ClipFullStylingStrategy.inheritBackgroundForNode()" );
var bgStyle = new Evernote.ClipStyle();
if ( !node ) {
return bgStyle;
}
var parent = node;
var styles = [ ];
var nodes = [ ];
var topElement = (document.body.parentNode) ? document.body.parentNode : document.body;
try {
while ( parent ) {
nodes.push( parent );
var filterFn = function ( prop, value ) {
return !(prop == "background-repeat" && (value == "no-repeat" || value == "repeat-y"));
};
var nodeStyle = new Evernote.ClipStyle( this.getNodeStyle( parent ), filterFn, Evernote.ClipStyle.CSS_GROUP.getExtForStyle( "background" ) );
if ( !nodeStyle.getStyle( "background-repeat" ) ) {
nodeStyle.removeStyle( "background-image" );
}
if ( !nodeStyle.getStyle( "background-color" ) && parent.getAttribute( "bgcolor" ) ) {
Evernote.Logger.debug( "Set bgcolor attribute: " + parent.getAttribute( "bgcolor" ) );
nodeStyle.addStyle( {"background-color":parent.getAttribute( "bgcolor" )} );
}
nodeStyle = this.evalBgPosition( node, parent, nodeStyle );
if ( nodeStyle.getStylesNames().length > 0 ) {
styles.push( nodeStyle );
Evernote.Logger.debug( "Add inh bg style " + nodeStyle.toString() );
}
if ( !recur || parent == topElement ) {
break;
}
else {
parent = parent.parentNode;
}
}
} catch(e) {
Evernote.Logger.error("ClipFullStylingStrategy.prototype.inheritBackgroundForNode failed to error " + e);
}
return styles;
};
Evernote.ClipFullStylingStrategy.prototype.evalBgPosition = function ( node, inhNode, nodeBgStyle ) {
Evernote.Logger.debug( "Dettermining background image offset" );
var strPosToPercent = {
"center":"50%",
"top":"0%",
"bottom":"100%",
"right":"100%",
"left":"0%"
};
var regExp = /url\((.*?)\)/;
var bgImage = nodeBgStyle.getStyle( "background-image" );
if ( !regExp.test( nodeBgStyle.getStyle( "background-image" ) ) || (bgImage && nodeBgStyle.getStyle( "background-image" ).indexOf( "data:image" ) >= 0) ) {
Evernote.Logger.debug( "bgStyle: " + nodeBgStyle.toString() );
return nodeBgStyle;
}
nodeBgStyle.addStyle( { "background-image": Evernote.StyleElementExtension.getPropertyValue(Evernote.ElementExtension.getComputedStyle( inhNode, null, this.getNodeView( inhNode ) ), Evernote.IEStylePropertiesMapping.getPropertyNameFor("background-image") ).replace( regExp, "url('$1')" ) } );
var actualImage = new Image();
actualImage.src = nodeBgStyle.getStyle( "background-image" ).match( regExp )[ 1 ].replace( /["']/g, "" );
var bgNodeRect = this.getOffsetRect( inhNode );
var nodeRect = this.getOffsetRect( node );
var yDelta = nodeRect.top - bgNodeRect.top;
var xDelta = nodeRect.left - bgNodeRect.left;
var bgNodeBgPosX = 0;
var bgNodeBgPosY = 0;
var origPosX = 0;
var origPosY = 0;
if ( nodeBgStyle.getStyle( "background-position" ) ) {
var bgPosition = nodeBgStyle.getStyle( "background-position" ).split( " " );
bgNodeBgPosX = strPosToPercent[bgPosition[ 0 ]] != null ? strPosToPercent[bgPosition[ 0 ]] : bgPosition[ 0 ];
bgNodeBgPosY = strPosToPercent[bgPosition[ 1 ]] != null ? strPosToPercent[bgPosition[ 1 ]] : bgPosition[ 1 ];
if ( bgNodeBgPosX && bgNodeBgPosX.indexOf( "%" ) > 0 ) {
origPosX = parseInt( bgNodeRect.width ) * (parseInt( bgNodeBgPosX ) / 100);
origPosX -= parseInt(actualImage.width) * (parseInt(bgNodeBgPosX) / 100);
}
else {
origPosX = parseInt( bgNodeBgPosX );
}
if ( bgNodeBgPosY && bgNodeBgPosY.indexOf( "%" ) > 0 ) {
origPosY = parseInt( bgNodeRect.height ) * (parseInt( bgNodeBgPosY ) / 100);
origPosY -= parseInt(actualImage.height) * (parseInt(bgNodeBgPosY) / 100);
}
else {
origPosY = parseInt( bgNodeBgPosY );
}
}
if ( isNaN( origPosX ) ) {
origPosX = 0;
}
if ( isNaN( origPosY ) ) {
origPosY = 0;
}
var xOffset = 0 - xDelta + origPosX;
var yOffset = 0 - yDelta + origPosY;
nodeBgStyle.addStyle( { "background-position":(xOffset + "px " + yOffset + "px") } );
Evernote.Logger.debug( "bgStyle: " + nodeBgStyle.toString() );
return nodeBgStyle;
};
Evernote.ClipFullStylingStrategy.prototype.getOffsetRect = function ( elem ) {
Evernote.Logger.debug( "ClipCSSStyleWalker.getOffsetRect()" );
var box = Evernote.ElementExtension.getBoundingClientRect(elem);
var body = elem.ownerDocument.body;
var docElem = elem.ownerDocument.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop || body.clientTop || 0;
var clientLeft = docElem.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top:Math.round( top ), left:Math.round( left ), width:box.width, height:box.height };
};</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.ClipRules = {
isNoKeepNodeAttr : function( attribute, nodeName, node ) {
if ( !attribute ) {
return true;
}
var attrName = attribute.name.toLowerCase();
var attrValue = attribute.value.toLowerCase();
if((node.nodeName.toUpperCase() == "SPAN" || node.nodeName.toUpperCase() == "A") && node.getElementsByTagName( "IMG" ).length > 0) {
nodeName = "div";
}
var attributesToKeepForNode = this.KEEP_NODE_ATTRIBUTES[nodeName];
if(attributesToKeepForNode) {
var keepAttributeForNode = typeof attributesToKeepForNode[attrName] != 'undefined';
}
return typeof this.NOKEEP_NODE_ATTRIBUTES[ attrName ] != 'undefined'
|| !keepAttributeForNode
|| attrName.substring( 0, 2 ) == "on"
|| attrName.indexOf("xml") == 0
|| attrValue.indexOf("function(") >= 0
|| (attrName == "href" && attrValue.substring( 0, 11 ) == "javascript:");
},
isConditionalNode : function( node ) {
return node && typeof this.CONDITIONAL_NODES[ node.nodeName.toUpperCase() ] != 'undefined';
},
translateNode : function( node ) {
var nodeName = this.NODE_NAME_TRANSLATIONS[ node.nodeName.toUpperCase() ] || node.nodeName.toUpperCase();
return (typeof this.SUPPORTED_NODES[ nodeName ] != "undefined") ? nodeName.toLowerCase() : this.NODE_NAME_TRANSLATIONS[ "*" ].toLowerCase();
},
isSupportedNode : function( node ) {
return node && typeof this.SUPPORTED_NODES[ node.nodeName.toUpperCase() ] != 'undefined';
},
isRejectedNode : function( node ) {
return node && typeof this.REJECTED_NODES[ node.nodeName.toUpperCase() ] != 'undefined';
},
isNonAncestorNode : function( node ) {
return node && typeof this.NON_ANCESTOR_NODES[ node.nodeName.toUpperCase() ] != 'undefined';
},
isSelfClosingNode : function( node ) {
return node && typeof this.SELF_CLOSING_NODES[ node.nodeName.toUpperCase() ] != 'undefined';
}
};
Evernote.ClipRules.KEEP_NODE_ATTRIBUTES = {
"a" : {
"title": null,
"dir" : null,
"accesskey": null,
"charset": null,
"type": null,
"name": null,
"href": null,
"hreflang": null,
"rel": null,
"rev": null,
"shape": null,
"coords": null,
"target": null
},
"abbr" : {
"title": null,
"dir" : null
},
"acronym" : {
"title": null,
"dir" : null
},
"address" : {
"title": null,
"dir" : null
},
"area" : {
"title": null,
"dir" : null,
"accesskey": null,
"shape": null,
"coords": null,
"href": null,
"nohref": null,
"alt": null,
"target": null
},
"b" : {
"title": null,
"dir" : null
},
"bdo" : {
"title": null,
"dir" : null
},
"big" : {
"title": null,
"dir" : null
},
"blockquote" : {
"title": null,
"dir" : null,
"cite": null
},
"br" : {
"title": null,
"clear": null
},
"caption" : {
"title": null,
"dir" : null,
"align": null
},
"center" : {
"title": null,
"dir" : null
},
"cite" : {
"title": null,
"dir" : null
},
"code" : {
"title": null,
"dir" : null
},
"col" : {
"title": null,
"dir" : null,
"span" : null,
"width" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null
},
"colgroup" : {
"title": null,
"dir" : null,
"span" : null,
"width" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null
},
"dd" : {
"title": null,
"dir" : null
},
"del" : {
"title": null,
"dir" : null,
"cite" : null,
"datetime" : null
},
"dfn" : {
"title": null,
"dir" : null
},
"div" : {
"title": null,
"dir" : null,
"align" : null
},
"dl": {
"title": null,
"dir" : null,
"compact" : null
},
"dt": {
"title": null,
"dir" : null
},
"em": {
"title": null,
"dir" : null
},
"font": {
"title": null,
"dir" : null,
"size" : null,
"color" : null,
"face" : null
},
"h1": {
"title": null,
"dir" : null,
"align" : null
},
"h2": {
"title": null,
"dir" : null,
"align" : null
},
"h3": {
"title": null,
"dir" : null,
"align" : null
},
"h4": {
"title": null,
"dir" : null,
"align" : null
},
"h5": {
"title": null,
"dir" : null,
"align" : null
},
"h6": {
"title": null,
"dir" : null,
"align" : null
},
"hr": {
"title": null,
"dir" : null,
"align" : null,
"noshade" : null,
"size" : null,
"width" : null
},
"i": {
"title": null,
"dir" : null
},
"img": {
"title": null,
"dir" : null,
"src" : null,
"alt" : null,
"name" : null,
"longdesc" : null,
"height" : null,
"width" : null,
"usemap" : null,
"ismap" : null,
"align" : null,
"border" : null,
"hspace" : null,
"vspace" : null
},
"en-media": {
"type" : null,
"hash" : null,
"title" : null,
"dir" : null,
"alt" : null,
"longdesc" : null,
"height" : null,
"width" : null,
"usemap" : null,
"align" : null,
"border" : null,
"hspace" : null,
"vspace" : null
},
"ins": {
"title": null,
"dir" : null,
"cite" : null,
"datetime" : null
},
"kbd": {
"title": null,
"dir" : null
},
"li": {
"title": null,
"dir" : null,
"type" : null,
"value" : null
},
"map": {
"dir" : null,
"title" : null,
"name" : null
},
"ol": {
"title" : null,
"dir" : null,
"type" : null,
"compact" : null,
"start" : null
},
"p": {
"title" : null,
"dir" : null,
"align" : null
},
"pre": {
"title" : null,
"dir" : null,
"width" : null
},
"s": {
"title" : null,
"dir" : null
},
"samp": {
"title" : null,
"dir" : null
},
"small": {
"title" : null,
"dir" : null
},
"span": {
"title" : null,
"dir" : null
},
"strike": {
"title" : null,
"dir" : null
},
"strong": {
"title" : null,
"dir" : null
},
"sub": {
"title" : null,
"dir" : null
},
"sup": {
"title" : null,
"dir" : null
},
"table": {
"title" : null,
"dir" : null,
"summary" : null,
"width" : null,
"border" : null,
"cellspacing" : null,
"cellpadding" : null,
"align" : null,
"bgcolor" : null
},
"tbody": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null
},
"td": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null,
"abbr" : null,
"rowspan" : null,
"colspan" : null,
"nowrap" : null,
"bgcolor" : null,
"width" : null,
"height" : null
},
"tfoot": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null
},
"th": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null,
"abbr" : null,
"rowspan" : null,
"colspan" : null,
"nowrap" : null,
"bgcolor" : null,
"width" : null,
"height" : null
},
"thead": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null
},
"tr": {
"title" : null,
"dir" : null,
"align" : null,
"char" : null,
"charoff" : null,
"valign" : null,
"bgcolor" : null
},
"tt": {
"title" : null,
"dir" : null
},
"u": {
"title" : null,
"dir" : null
},
"ul": {
"title" : null,
"dir" : null,
"type" : null,
"compact" : null
},
"var": {
"title" : null,
"dir" : null
}
};
Evernote.ClipRules.NOKEEP_NODE_ATTRIBUTES = {
"style" : null,
"tabindex" : null
};
Evernote.ClipRules.CONDITIONAL_NODES = {
"EMBED" : null,
"OBJECT" : null,
"IMG" : null,
"VIDEO" : null
};
Evernote.ClipRules.NODE_NAME_TRANSLATIONS = {
"HTML" : "DIV",
"BODY" : "DIV",
"FORM" : "DIV",
"CANVAS" : "DIV",
"CUFON" : "DIV",
"EMBED" : "IMG",
"BUTTON" : "SPAN",
"INPUT" : "SPAN",
"LABEL" : "SPAN",
"BDI" : "SPAN",
"IMG" : "EN-MEDIA",
"*" : "DIV"
};
Evernote.ClipRules.SUPPORTED_NODES = {
"A" : null,
"ABBR" : null,
"ACRONYM" : null,
"ADDRESS" : null,
"AREA" : null,
"B" : null,
"BUTTON" : null,
"BDO" : null,
"BIG" : null,
"BLOCKQUOTE" : null,
"BR" : null,
"CAPTION" : null,
"CENTER" : null,
"CITE" : null,
"CODE" : null,
"COL" : null,
"COLGROUP" : null,
"DD" : null,
"DEL" : null,
"DFN" : null,
"DIV" : null,
"DL" : null,
"DT" : null,
"EM" : null,
"FONT" : null,
"FORM" : null,
"H1" : null,
"H2" : null,
"H3" : null,
"H4" : null,
"H5" : null,
"H6" : null,
"HR" : null,
"HTML" : null,
"I" : null,
"IMG" : null,
"EN-MEDIA" : null,
"INPUT" : null,
"INS" : null,
"KBD" : null,
"LI" : null,
"MAP" : null,
"OL" : null,
"P" : null,
"PRE" : null,
"Q" : null,
"S" : null,
"SAMP" : null,
"SMALL" : null,
"SPAN" : null,
"STRIKE" : null,
"STRONG" : null,
"SUB" : null,
"SUP" : null,
"TABLE" : null,
"TBODY" : null,
"TD" : null,
"TFOOT" : null,
"TH" : null,
"THEAD" : null,
"TR" : null,
"TT" : null,
"U" : null,
"UL" : null,
"VAR" : null
};
Evernote.ClipRules.REJECTED_NODES = {
"SCRIPT" : null,
"LINK" : null,
"IFRAME" : null,
"STYLE" : null,
"SELECT" : null,
"OPTION" : null,
"OPTGROUP" : null,
"NOSCRIPT" : null,
"PARAM" : null,
"HEAD" : null,
"EVERNOTEDIV" : null,
"CUFONTEXT" : null,
"NOEMBED" : null
};
Evernote.ClipRules.NON_ANCESTOR_NODES = {
"OL" : null,
"UL" : null,
"LI" : null
};
Evernote.ClipRules.SELF_CLOSING_NODES = {
"IMG" : null,
//"INPUT" : null,
"BR" : null
};
</script><script charset="ANSI" defer="" type="text/javascript">/**
* ClipStyle is a container for CSS styles. It is able to add and remove
* CSSStyleRules (and parse CSSRuleList's for rules), as well as
* CSSStyleDeclaration's and instances of itself.
* ClipStyle provides a mechanism to serialize itself via toString(), and
* reports its length via length property. It also provides a method to clone
* itself and expects to be manipulated via addStyle and removeStyle.
*/
Evernote.ClipStyle = function ClipStyle( css, filterFn, styleList ) {
this.initialize( css, filterFn, styleList );
};
Evernote.ClipStyle.STYLES = [
"background", "background-attachment", "background-clip", "background-color", "background-image", "background-origin", "background-position-x", "background-position-y", "background-position", "background-repeat", "background-size",
"border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
"border-left", "border-left-color", "border-left-style", "border-left-width",
"border-right", "border-right-color", "border-right-style", "border-right-width",
"border-top", "border-top-color", "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width",
"border-collapse", "border-spacing", "bottom", "box-shadow",
"caption-side", "clear", "clip", "color", "content", "counter-increment", "counter-reset", "cursor",
"direction", "display",
"empty-cells",
"float", "font", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight",
"height",
"ime-mode",
"left", "letter-spacing", "line-height", "list-style", "list-style-image", "list-style-position", "list-style-type",
"margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "marker-offset", "max-height", "max-width", "min-height", "min-width",
"opacity", "outline", "outline-color", "outline-offset", "outline-style", "outline-width", "overflow", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "page-break-after", "page-break-before", "pointer-events", "position",
"resize", "right",
"table-layout", "text-align", "text-anchor", "text-decoration", "text-indent", "text-overflow", "text-shadow", "text-transform", "top",
"vertical-align", "visibility",
"white-space", "width", "word-spacing", "word-wrap",
"z-index"
];
Evernote.ClipStyle.NO_INHERIT_STYLES = {
"*":[ "background", "background-image", "background-color", "background-position", "background-repeat",
"border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
"border-left", "border-left-color", "border-left-style", "border-left-width",
"border-right", "border-right-color", "border-right-style", "border-right-width",
"border-top", "border-top-color", "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width",
"border-collapse", "border-spacing", "bottom",
"clear",
"display",
"float",
"height",
"left", "list-style",
"margin", "margin-bottom", "margin-left", "margin-right", "margin-top",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"right",
"text-decoration", "top",
"width" ],
"img":[ "height", "width" ]
};
Evernote.ClipStyle.CSS_GROUP = {
"margin":[ "left", "right", "top", "bottom" ],
"padding":[ "left", "right", "top", "bottom" ],
"border":[ "width", "style", "color" ],
"border-bottom":[ "width", "style", "color" ],
"border-top":[ "width", "style", "color" ],
"border-right":[ "width", "style", "color" ],
"border-left":[ "width", "style", "color" ],
"border-image":[ "outset", "repeat", "slice", "source", "width" ],
"background":[ "attachment", "color", "image", "position", "repeat", "clip", "origin", "size" ],
"font":[ "family", "size", "style", "variant", "weight", "size-adjust", "stretch", "+line-height" ],
"list-style":[ "image", "position", "type" ]
};
Evernote.ClipStyle.CSS_GROUP.getExtForStyle = function ( name ) {
var list = this[ name ];
var extList = [ ];
if ( list ) {
for ( var i = 0; i < list.length; ++i ) {
if ( list[ i ].indexOf( "+" ) >= 0 ) {
var tmp = list[ i ];
extList.push( tmp.replace( "+", "" ) );
}
else {
extList.push( name + "-" + list[ i ] );
}
}
return extList;
}
return null;
};
Evernote.ClipStyle.STYLE_ATTRIBUTES = {
"bgcolor":"background-color",
"text":"color"
};
Evernote.ClipStyle.INHERITED_STYLES = [
"azimuth",
"border-collapse", "border-spacing",
"caption-side", "color", "cursor",
"direction",
"elevation", "empty-cells",
"font-family", "font-size", "font-style", "font-weight", "font",
"letter-spacing", "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style",
"orphans",
"pitch-range", "pitch",
"quotes",
"richness",
"speak-header", "speak-numeral", "speak-punctuation", "speak", "speak-rate", "stress",
"text-align", "text-indent", "text-transform",
"visibility", "voice-family", "volume",
"white-space", "widows", "word-spacing"
];
Evernote.ClipStyle.prototype._collection = null;
Evernote.ClipStyle.prototype._filterFn = null;
Evernote.ClipStyle.prototype._styleList = null;
Evernote.ClipStyle.prototype.initialize = function ( css, filterFn, styleList ) {
Evernote.Logger.debug( "ClipStyle.initialize()" );
this._collection = new Evernote.StylesCollection();
Evernote.Logger.debug( "ClipStyle.initialize: collection initialized()" );
this._filterFn = (typeof filterFn == "function") ? filterFn : null;
this._styleList = (styleList != null) ? styleList : Evernote.ClipStyle.STYLES;
if(css) {
if ( window.CSSStyleDeclaration && css instanceof window.CSSStyleDeclaration ) {
this.addStyle( css, this._styleList );
}
else if ( window.CSSStyleRule && css instanceof window.CSSStyleRule ) {
this.addStyle( css.style, this._styleList );
}
else if ( (window.CSSRuleList && css instanceof window.CSSRuleList) || css instanceof Array ) {
for ( var i = 0; i < css.length; ++i ) {
this.addStyle( css[ i ].style, this._styleList );
}
}
else if ( typeof css == 'object' && css != null ) {
this.addStyle( css, this._styleList );
}
}
Evernote.Logger.debug( "ClipStyle.initialize() end ");
};
Evernote.ClipStyle.prototype.fixBackground = function ( prop, value ) {
if(prop && value) {
if(prop.indexOf("background-image") != -1 && value.indexOf("url") != -1) {
Evernote.Logger.debug("Start replace");
var regExp = /url\((.*?)\)/;
var res = value.replace(regExp, "url('$1')").replace(/('")|("')|('')/g, "'");
Evernote.Logger.debug("End replace");
return Evernote.GlobalUtils.escapeXML(res);
}
}
return value;
};
Evernote.ClipStyle.prototype.addStyle = function ( style, styleList ) {
Evernote.Logger.debug( "ClipStyle.addStyle()" );
if ( window.CSSStyleDeclaration && style instanceof window.CSSStyleDeclaration && style.length > 0 ) {
var list = (styleList != null) ? styleList : this._styleList;
for ( var i = 0; i < list.length; ++i ) {
var prop = list[ i ];
var value = Evernote.StyleElementExtension.getPropertyValue(style, prop );
var importantPriority = !!((style.getPropertyPriority(prop) == 'important'));
value = this.fixBackground(prop, value);
this.addSimpleStyle( prop, value, importantPriority );
}
}
else if ( style instanceof Evernote.ClipStyle ) {
list = (styleList != null) ? styleList : style.getStylesNames();
for ( var i = 0; i < list.length; ++i ) {
var prop = list[ i ];
value = style.getStyle( prop );
importantPriority = style.isImportant( prop );
value = this.fixBackground(prop, value);
this.addSimpleStyle( prop, value, importantPriority );
}
}
else if ( typeof style == 'object' && style != null ) {
list = (styleList != null) ? styleList : style;
for ( var prop in list ) {
// In some cases, attempt to get currentStyle.outline ( or outlineWidth ) property in IE8 throws
// 'unspecified error' and crash whole serilization process. So we wrap it into try {...} catch.
try {
if ( list.hasOwnProperty( prop ) ) {
var usedStyle = style[ prop ];
var pName = prop;
if(!usedStyle) {
usedStyle = style [list[prop]];
pName = list[prop];
if(!usedStyle) {
var propName = Evernote.IEStylePropertiesMapping.getPropertyNameFor(list[prop]);
if(propName) {
usedStyle = style[propName[1]];
}
}
}
usedStyle = this.fixBackground(pName, usedStyle);
this.addSimpleStyle( pName, usedStyle );
}
} catch (err) {}
}
}
};
Evernote.ClipStyle.prototype.removeStyle = function ( style ) {
Evernote.Logger.debug( "ClipStyle.removeStyle()" );
if(style) {
if ( window.CSSStyleDeclaration && Evernote.Utils.isInstanceOf(style, window.CSSStyleDeclaration) || style instanceof Array ) {
for ( var i = 0; i < style.length; ++i ) {
this.removeSimpleStyle( style[ i ] );
}
}
else if ( style instanceof Evernote.ClipStyle ) {
var stylesNames = style.getStylesNames();
for ( i = 0; i < stylesNames.length; ++i ) {
this.removeSimpleStyle( stylesNames[ i ] );
}
}
else if ( typeof style == 'string' ) {
this.removeSimpleStyle( style );
}
}
Evernote.Logger.debug("ClipStyle.removeStyle() end")
};
Evernote.ClipStyle.prototype.mergeStyle = function ( style, override ) {
Evernote.Logger.debug( "ClipStyle.mergeStyle()" );
if ( style instanceof Evernote.ClipStyle ) {
var stylesNames = style.getStylesNames();
for ( var i = 0; i < stylesNames.length; ++i ) {
var styleName = stylesNames[ i ];
var styleValue = this._collection.getStyle( styleName );
if ( styleValue == null || override || (style.isImportant( styleName ) && !this._collection.isImportant( styleName )) ) {
var newValue = style.getStyle( styleName );
if ( style.isImportant( styleName ) ) {
this._collection.addStyle( styleName, newValue, true );
}
else if ( override && !this._collection.isImportant( styleName ) ) {
this._collection.addStyle( styleName, newValue, false );
}
else if ( styleValue == null && !override ) {
this._collection.addStyle( styleName, newValue, style.isImportant( styleName ) );
}
}
}
}
};
Evernote.ClipStyle.prototype.getStylesNames = function () {
return this._collection.getStylesNames();
};
Evernote.ClipStyle.prototype.getStyle = function ( prop ) {
return this._collection.getStyle( prop );
};
Evernote.ClipStyle.prototype.isImportant = function ( prop ) {
return this._collection.isImportant( prop );
};
Evernote.ClipStyle.prototype.addSimpleStyle = function ( prop, value, importantPriority ) {
if ( typeof this._filterFn == "function" && !this._filterFn( prop, value ) ) {
return;
}
var impl = Evernote.StylesReplacementRegistry.getImplementationFor(prop);
if(impl && impl.getValue) {
value = impl.getValue(value);
}
this._collection.addStyle( prop, value, importantPriority );
};
Evernote.ClipStyle.prototype.removeSimpleStyle = function ( prop ) {
this._collection.removeStyle( prop );
};
Evernote.ClipStyle.prototype.toString = function () {
var str = "";
var stylesNames = this.getStylesNames();
for ( var i = 0; i < stylesNames.length; ++i ) {
var styleName = stylesNames[ i ];
var value = this._collection.getStyle( styleName );
if ( value != null && value.length > 0 ) {
str += styleName + ":" + value + ";";
}
}
return str;
};
Evernote.ClipStyle.CSSDefaultStyle = {
"background-attachment": "scroll",
"background-color" : "transparent",
"background-image" : "none",
"background-position-x" : "0px",
"background-position-y" : "0px",
"background-repeat" : "repeat",
"border-bottom-style" : "none",
"border-bottom-width" : "medium",
"border-left-style" : "none",
"border-left-width" : "medium",
"border-right-style" : "none",
"border-right-width" : "medium",
"border-top-style" : "none",
"border-top-width" : "medium",
"border-collapse" : "separate",
"bottom" : "auto",
"clear" : "none",
"height" : "auto",
"left" : "auto",
"margin-bottom" : "0px",
"margin-left" : "0px",
"margin-right" : "0px",
"margin-top" : "0px",
"max-height" : "none",
"max-width" : "none",
"min-height" : "0px",
"min-width" : "0px",
"overflow" : "visible",
"overflow-x" : "visible",
"overflow-y" : "visible",
"padding" : "0px",
"padding-bottom" : "0px",
"padding-left" : "0px",
"padding-right" : "0px",
"padding-top" : "0px",
"page-break-before" : "auto",
"page-break-after" : "auto",
"position" : "static",
"right" : "auto",
"text-align" : "left",
"text-decoration" : "none",
"text-indent" : "0px",
"text-overflow" : "clip",
"top" : "auto",
"width" : "auto"
};
Evernote.ClipStyle.prototype.removeDefaultCssStyle = function () {
var stylesNames = this.getStylesNames();
for ( var i = 0; i < stylesNames.length; ++i ) {
var styleName = stylesNames[ i ];
var defaultCssValue = Evernote.ClipStyle.CSSDefaultStyle[styleName];
var value = this.getStyle( styleName );
if (!value)
continue;
if (defaultCssValue == value) {
this.removeStyle(styleName);
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ClipStyleProperty = function ClipStyleProperty( name, value, isImportant ) {
this.initialize( name, value, isImportant );
};
Evernote.ClipStyleProperty.prototype.initialize = function( name, value, isImportant ) {
if ( typeof name == "string" && typeof value == "string" ) {
this._name = name;
this._value = value;
}
this._isImportant = (isImportant) ? true : false;
};
Evernote.ClipStyleProperty.prototype._name = null;
Evernote.ClipStyleProperty.prototype._value = null;
Evernote.ClipStyleProperty.prototype._isImportant = null;
Evernote.ClipStyleProperty.prototype.name = function() {
return this._name;
};
Evernote.ClipStyleProperty.prototype.value = function() {
return this._value;
};
Evernote.ClipStyleProperty.prototype.isImportant = function() {
return this._isImportant;
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Represents DOM parser that could able to traverse the DOM node tree from specified root.
* @param tab - current window object
* @param range - current selection on the page (if any)
* @constructor
*/
Evernote.DomParser = function DomParser( tab, range ) {
this.initialize( tab, range );
};
Evernote.DomParser.prototype._tab = null;
/**
* Update current parser data
* @param tab - current window object
* @param range - current selection on the page (if any)
*/
Evernote.DomParser.prototype.initialize = function ( tab, range ) {
Evernote.Logger.debug( "DomSerializer.initialize()" );
this._tab = tab;
this._range = range;
};
/**
* Determines if passed node should be serialized.
* Node should not be initialized if one of the following is true:
* - node is rejected according to configuration
* - there is the selection on the page and this node is out of selection range.
* @param node - DOM node
* @return {Boolean}
*/
Evernote.DomParser.prototype.isNodeForSerialize = function ( node ) {
if ( !node || Evernote.ClipRules.isRejectedNode( node ) || node.id == "evernoteContentClipperWait" ) {
return false;
}
if(Evernote.ClipperElementsIdentifiers.match(node)) {
Evernote.Logger.debug("Node is rejected because it is clipper information " + node.id);
return false;
}
return (!this._range || this.isNodeInRange( node )) ? true : false;
};
/**
* Determines whether passed node is inside the selection range. Returns true if it is, false otherwise.
* @param node - DOM node
* @return {Boolean}
*/
Evernote.DomParser.prototype.isNodeInRange = function ( node ) {
Evernote.Logger.debug( "DomParser.isNodeInRange()" );
try {
if ( node && this._range ) {
var nodeRange = node.ownerDocument.createRange();
try {
nodeRange.selectNode( node );
}
catch ( e ) {
nodeRange.selectNodeContents( node );
}
return this._range.compareBoundaryPoints( Range.START_TO_END, nodeRange ) == 1
&& this._range.compareBoundaryPoints( Range.END_TO_START, nodeRange ) == -1;
}
} catch(e) {
//We're in quirk mode, allow to clip node
return true;
}
//If we failed to find any
return false;
};
/**
* Determines whether passed node is visible on the page.
* @param node - DOM node.
* @return {Boolean}
*/
Evernote.DomParser.prototype.isNodeVisible = function ( node ) {
Evernote.Logger.debug( "DomParser.isNodeVisible()" );
if ( !node ) {
return false;
}
var compStyles = Evernote.ElementExtension.getComputedStyle( node, null, this._tab );
return Evernote.StyleElementExtension.getPropertyValue(compStyles, "display" ) != "none";
};
Evernote.DomParser.prototype.parseAsync = function ( root, fullPage, serializer, callback ) {
var PARSING_TIMEOUT_INTERVAL = 1000; //milliseconds
if (!callback) {
this.parse(root, fullPage, serializer);
return;
}
if ( !root ) {
throw new Error( "No root element for parsing" );
}
var node = root;
var parentNode = null;
var thizz = this;
var asyncParser = function()
{
var parsingEnd = true;
var startTimeParsing = new Date().getTime();
while ( node ) {
if ( node != root && node.parentNode ) {
parentNode = node.parentNode.serializedNode;
}
if ( thizz.isNodeForSerialize( node ) ) {
if ( node.nodeType == Evernote.Node.TEXT_NODE ) {
serializer.textNode( node, this._range );
}
else if ( node.nodeType == Evernote.Node.ELEMENT_NODE && thizz.isNodeVisible( node ) ) {
node.serializedNode = serializer.startNode( new Evernote.SerializedNode( node, parentNode ), root, fullPage );
if ( node.hasChildNodes() ) {
node = node.childNodes[ 0 ];
continue;
}
else {
serializer.endNode( node.serializedNode );
if ( node.serializedNode ) {
try {
delete node.serializedNode;
} catch(e) {
//If we are failed to delete the property, than just set it to undefined
node.serializedNode = undefined;
}
}
}
}
}
/**
* Check if there is a next node available and it is not the root
*/
if ( node.nextSibling && node != root ) {
node = node.nextSibling;
}
else if ( node != root ) {
while ( node.parentNode && node != root ) {
node = node.parentNode;
try {
serializer.endNode( node.serializedNode );
} catch (err) {
node.serializedNode = undefined;
continue;
};
try {
delete node.serializedNode;
} catch (e) {
//If we are failed to delete the property, than just set it to undefined
node.serializedNode = undefined;
}
if ( node.nextSibling && node != root ) {
node = node.nextSibling;
break;
}
}
if ( node == root ) {
break;
}
}
else {
break;
}
var endTimeParsing = new Date().getTime();
if ( (endTimeParsing - startTimeParsing) >= PARSING_TIMEOUT_INTERVAL ) {
Evernote.Logger.debug("Parsing interval timeout: " + (endTimeParsing - startTimeParsing));
parsingEnd = false;
break;
}
}
if (parsingEnd) {
Evernote.Logger.debug("Parsing end");
callback();
}else {
Evernote.Logger.debug("Parsing repeat");
setTimeout(asyncParser, 0);
}
};
setTimeout(asyncParser, 0);
};
/**
* Starts parsing from specified root.
* @param root - starting DOM node.
* @param fullPage - is user selects to serialize the full page
* @param serializer - current serializer to be used to serialize the DOM node to string
*/
Evernote.DomParser.prototype.parse = function ( root, fullPage, serializer ) {
Evernote.Logger.debug( "DomParser.parse()" );
if ( !root ) {
throw new Error( "No root element for parsing" );
}
var node = root;
var parentNode = null;
while ( node ) {
if ( node != root && node.parentNode ) {
parentNode = node.parentNode.serializedNode;
}
if ( this.isNodeForSerialize( node ) ) {
if ( node.nodeType == Evernote.Node.TEXT_NODE ) {
serializer.textNode( node, this._range );
}
else if ( node.nodeType == Evernote.Node.ELEMENT_NODE && this.isNodeVisible( node ) ) {
node.serializedNode = serializer.startNode( new Evernote.SerializedNode( node, parentNode ), root, fullPage );
if ( node.hasChildNodes() ) {
node = node.childNodes[ 0 ];
continue;
}
else {
serializer.endNode( node.serializedNode );
if ( node.serializedNode ) {
try {
delete node.serializedNode;
} catch(e) {
//If we are failed to delete the property, than just set it to undefined
node.serializedNode = undefined;
}
}
}
}
}
/**
* Check if there is a next node available and it is not the root
*/
if ( node.nextSibling && node != root ) {
node = node.nextSibling;
}
else if ( node != root ) {
while ( node.parentNode && node != root ) {
node = node.parentNode;
try {
serializer.endNode( node.serializedNode );
} catch (err) {
node.serializedNode = undefined;
continue;
};
try {
delete node.serializedNode;
} catch (e) {
//If we are failed to delete the property, than just set it to undefined
node.serializedNode = undefined;
}
if ( node.nextSibling && node != root ) {
node = node.nextSibling;
break;
}
}
if ( node == root ) {
break;
}
}
else {
break;
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.NodeSerializer = function NodeSerializer( tab, styleStrategy, includeBg ) {
this.initialize( tab, styleStrategy, includeBg );
};
Evernote.NodeSerializer.prototype._tab = null;
Evernote.NodeSerializer.prototype._styleStrategy = null;
Evernote.NodeSerializer.prototype._docBase = null;
Evernote.NodeSerializer.prototype._imagesUrls = null;
Evernote.NodeSerializer.prototype._serializedDom = "";
Evernote.NodeSerializer.prototype._includeBgStyles = true;
Evernote.NodeSerializer.prototype.initialize = function ( tab, styleStrategy, includeBg ) {
Evernote.Logger.debug( "DomSerializer.initialize()" );
this._tab = tab;
this._styleStrategy = (styleStrategy instanceof Evernote.ClipStylingStrategy) ? styleStrategy : null;
this._imagesUrls = [ ];
this._includeBgStyles = ( includeBg != null ) ? includeBg : true;
this.getDocumentBase();
};
Evernote.NodeSerializer.prototype.startNode = function ( serializedNode, root, fullPage ) {
Evernote.Logger.debug( "Start to serialize node :" + serializedNode.node.nodeName + ", class = " + serializedNode.node.className + ", id = " + serializedNode.node.id );
try {
var node = serializedNode.node;
if ( Evernote.ClipRules.isConditionalNode( node ) && Evernote.ElementSerializerFactory.getImplementationFor( node ) != null ) {
var result = this.serializeConditionalNode( node, root, fullPage );
this._serializedDom += result.content;
// hack for desktop Win client
if ( result.imageUrl ) {
this._imagesUrls.push( result.imageUrl );
}
serializedNode.setStyle(result.nodeStyle);
return serializedNode;
}
if ( node.nodeName.toLowerCase() == "embed" ) {
var src = node.getAttribute( "src" );
if ( src && (src.indexOf(".swf", src.length - ".swf".length) !== -1) ) {
serializedNode.setStyle(new Evernote.ClipStyle());
return serializedNode;
}
}
if ( node.nodeName.toLowerCase() == "img" ) {
var src = node.getAttribute( "src" );
if (src.indexOf('&') != -1) {
src = src.slice(0, src.indexOf('&'));
}
var absoluteSource = Evernote.Utils.makeAbsolutePath(this._docBase, src).replace(/\s/g, "%20");
node.setAttribute( "type", "put-media-type-here-for-" + absoluteSource);
node.setAttribute( "hash", "put-hash-type-here-for-" + absoluteSource);
node.setAttribute( "src", src);
if ( src && src.indexOf( "data:image" ) < 0 ) {
this._imagesUrls.push( src );
}
}
var attrsStr = this.serializeAttributes( node );
var stylesStr = "";
var nodeName = Evernote.ClipRules.translateNode( node );
if ( this._styleStrategy ) {
var nodeStyle = this._styleStrategy.styleForNode( node, root, fullPage, Evernote.ClipStyleType.Default ).evaluated;
var inhBgStyle = null;
if ( this._includeBgStyles )
inhBgStyle = this._styleStrategy.styleForNode( node, root, fullPage, Evernote.ClipStyleType.InheritedBgStyle ).inheritedBackground;
if ( inhBgStyle != null )
for ( var inhI = inhBgStyle.length - 1; inhI >= 0; inhI-- ) {
var inhStyle = inhBgStyle[inhI];
this._serializedDom += "<div " + this.serializeStyles( node, inhStyle ) + " >
";
serializedNode.translateTo.push( "div" );
}
var pseudoStyle = this._styleStrategy.getNodeStyle( node, null, ":before" );
if ( fullPage && node.nodeName.toLowerCase() == "body" ) {
var wrapBodyStyle = new Evernote.ClipStyle( nodeStyle, null, Evernote.ClipStyle.CSS_GROUP.getExtForStyle( "background" ) );
this._serializedDom += "<" + "div" + " " + this.serializeStyles( node, wrapBodyStyle ) + " >";
serializedNode.translateTo.push( "div" );
var bgGroup = Evernote.ClipStyle.CSS_GROUP.getExtForStyle( "background" );
for ( var ind in bgGroup ) {
if ( bgGroup.hasOwnProperty( ind ) ) {
nodeStyle.removeStyle( bgGroup[ind] );
}
}
}
if ( !fullPage && node == root ) {
nodeStyle.removeStyle( "float" );
}
if ( !serializedNode.node.hasChildNodes() && !(nodeStyle.getStyle( "height" ) || node.getAttribute( "height" )) ) {
nodeStyle.addStyle( {height:"0px"} );
}
if ( !serializedNode.node.hasChildNodes() && !(nodeStyle.getStyle( "width" ) || node.getAttribute( "width" )) ) {
nodeStyle.addStyle( {width:"0px"} );
}
if(nodeStyle.getStyle("position") == "fixed") {
nodeStyle.addStyle({position: "absolute"});
}
if ( (node.nodeName.toUpperCase() == "SPAN"/* || node.nodeName.toUpperCase() == "A"*/) && node.getElementsByTagName( "IMG" ).length > 0) {
nodeName = "div";
if ( !nodeStyle.getStyle( "display" ) )
nodeStyle.addStyle( {display:"inline"} );
}
if (node.nodeName.toUpperCase() == "TH" || node.nodeName.toUpperCase() == "TD") {
nodeStyle.addStyle( {display:"table-cell"} );
}
nodeStyle.removeDefaultCssStyle();
this._serializedDom += this.serializePseudoElement( node, pseudoStyle );
stylesStr = this.serializeStyles( node, nodeStyle );
if ( (nodeName.toLowerCase() == "div" /*|| nodeName.toLowerCase() == "span"*/) && nodeStyle.getStyle( "float" ) && nodeStyle.getStyle( "float" ) != "none" && serializedNode.parentNode && node.parentNode.nodeName.toLowerCase() != "a" ) {
if ( !serializedNode.node.nextSibling || serializedNode.node.nextSibling.nodeType == 3 )
serializedNode.parentNode.isInlineBlock = true;
}
}
Evernote.Logger.debug( node.nodeName + " " + attrsStr + " -> " + nodeName + " " + stylesStr );
this._serializedDom += "<" + nodeName + " " + attrsStr + " " + stylesStr + " >";
serializedNode.setStyle(nodeStyle);
serializedNode.translateTo.push( nodeName );
return serializedNode;
}
catch ( e ) {
Evernote.Logger.error( "Failed to start serialize node :" + e );
throw e;
}
};
Evernote.NodeSerializer.prototype.serializePseudoElement = function ( node, pseudoStyle ) {
try {
var nodeName = Evernote.ClipRules.translateNode( node );
if ( pseudoStyle.getStylesNames().length > 0 ) {
var content = " ";
if ( pseudoStyle.getStyle( "content" ) ) {
content = pseudoStyle.getStyle( "content" );
pseudoStyle.removeStyle( "content" );
}
var beforeStylesStr = this.serializeStyles( node, pseudoStyle );
return "<" + nodeName + " " + beforeStylesStr + " >" + content.replace( /"/g, '' ) + "</" + nodeName + ">";
}
return "";
}
catch ( e ) {
Evernote.Logger.error( "Failed to serialize pseudo element :" + e );
throw e;
}
};
Evernote.NodeSerializer.prototype.textNode = function ( node, range ) {
this._serializedDom += this.serializeTextNode( node, range );
};
Evernote.NodeSerializer.prototype.endNode = function ( serializedNode ) {
try {
Evernote.Logger.debug( "end serialize node :" + serializedNode.translateTo );
if ( serializedNode.isInlineBlock ) {
var name = "div";
if ( serializedNode.node.nodeName.toLowerCase() == "ul" ) {
name = "li"
}
this._serializedDom += "<" + name + " style=\"clear: both; width: 0px; height: 0px;\">" + " " + "</" + name + ">"
}
var node = serializedNode.node;
var serializedPseudo = "";
var pseudoStyle = new Evernote.ClipStyle();
if ( this._styleStrategy ) {
pseudoStyle = this._styleStrategy.getNodeStyle( node, null, ":after" );
if ( pseudoStyle.getStylesNames().length > 0 ) {
var floatStyle = serializedNode.getStyle().getStyle( "float" );
if ( floatStyle && !pseudoStyle.getStyle( "float" ) )
pseudoStyle.addStyle( { "float" : floatStyle } );
if ( node.nodeName.toLowerCase() == "ul" )
serializedPseudo = this.serializePseudoElement( document.createElement( "div" ), pseudoStyle );
}
}
while ( serializedNode.translateTo.length > 0 ) {
var nodeName = serializedNode.translateTo.pop();
if ( !Evernote.ClipRules.isSelfClosingNode( serializedNode.node ) ) {
if ( !serializedNode.node.hasChildNodes() )
this._serializedDom += " ";
}
if ( nodeName.toLowerCase() == "ul" ) {
this._serializedDom += this.serializePseudoElement( document.createElement( "li" ), pseudoStyle );
}
this._serializedDom += "</" + nodeName + ">";
}
this._serializedDom += serializedPseudo;
}
catch ( e ) {
Evernote.Logger.error( "Failed to end serialize node :" + e );
throw e;
}
};
Evernote.NodeSerializer.prototype.serializeTextNode = function ( node, range ) {
Evernote.Logger.debug( "DomSerializer.serializeTextNode()" );
try {
var nodeValue = node.nodeValue;
if ( !range ) {
return Evernote.Utils.htmlEncode( nodeValue );
}
else {
if ( range.startContainer == node && range.startContainer == range.endContainer ) {
return Evernote.Utils.htmlEncode( nodeValue.substring( range.startOffset, range.endOffset ) );
}
else if ( range.startContainer == node ) {
return Evernote.Utils.htmlEncode( nodeValue.substring( range.startOffset ) );
}
else if ( range.endContainer == node ) {
return Evernote.Utils.htmlEncode( nodeValue.substring( 0, range.endOffset ) );
}
else if ( range.commonAncestorContainer != node ) {
return Evernote.Utils.htmlEncode( nodeValue );
}
}
}
catch ( e ) {
Evernote.Logger.error( "DomSerializer.serializeTextNode() failed " + e );
throw e;
}
return "";
};
Evernote.NodeSerializer.prototype.serializeConditionalNode = function ( node, root, fullPage ) {
Evernote.Logger.debug( "DomSerializer.serializeConditionalNode()" );
var impl = Evernote.ElementSerializerFactory.getImplementationFor( node );
if ( typeof impl == 'function' ) {
var nodeStyle = (this._styleStrategy) ? this._styleStrategy.styleForNode( node, root, fullPage ).evaluated : null;
if (nodeStyle)
nodeStyle.removeDefaultCssStyle();
var serializer = new impl( node, nodeStyle );
var content = serializer.serialize( this._docBase );
var imageUrl = serializer.getImageUrl();
return { content:content, imageUrl:imageUrl, nodeStyle:nodeStyle };
}
return { content:"", imageUrl:"", nodeStyle:new Evernote.ClipStyle() };
};
Evernote.NodeSerializer.prototype.serializeAttributes = function ( node ) {
Evernote.Logger.debug( "DomSerializer.serializeAttributes()" );
try {
var attrs = node.attributes;
var str = "";
for ( var i = 0; i < attrs.length; ++i ) {
if ( !Evernote.ClipRules.isNoKeepNodeAttr( attrs[ i ], Evernote.ClipRules.translateNode( node ), node ) ) {
var attrValue = (attrs[ i ].value) ? Evernote.GlobalUtils.escapeXML( attrs[ i ].value ) : "";
if ( (attrs[ i ].name.toLowerCase() == "src" || attrs[ i ].name.toLowerCase() == "href") && attrValue.toLowerCase().indexOf( "http" ) != 0 ) {
attrValue = Evernote.Utils.makeAbsolutePath( this._docBase, attrValue );
}
str += " " + attrs[ i ].name.toLowerCase() + "=\"" + attrValue + "\"";
}
}
return str;
}
catch ( e ) {
Evernote.Logger.error( "DomSerializer.serializeAttributes() failed: error = " + e );
}
return "";
};
Evernote.NodeSerializer.prototype.serializeStyles = function ( node, nodeStyle ) {
Evernote.Logger.debug( "DomSerializer.serializeStyles()" );
try {
var str = "";
if(node.nodeName.toLowerCase() == "map") {
//Map should not have style attribute according to Evernote DTD
return "";
}
if ( node && nodeStyle instanceof Evernote.ClipStyle ) {
str += " style=\"" + nodeStyle.toString().replace( /"/g, "" ) + "\"";
}
return str;
}
catch ( e ) {
Evernote.Logger.error( "DomSerializer.serializeStyles() failed: error = " + e );
throw e;
}
return "";
};
Evernote.NodeSerializer.prototype.getDocumentBase = function () {
Evernote.Logger.debug( "DomSerializer.getDocumentBase()" );
if ( !this._docBase ) {
var baseTags = this._tab.document.getElementsByTagName( "base" );
for ( var i = 0; i < baseTags.length; ++i ) {
var baseTag = baseTags[ i ];
if ( typeof baseTag == 'string' && baseTag.indexOf( "http" ) == 0 ) {
this._docBase = baseTag;
}
if ( this._docBase ) {
break;
}
}
if ( !this._docBase ) {
var location = this._tab.document.location;
this._docBase = location.protocol + "//" + location.host + location.pathname.replace( /[^\/]+$/, "" );
}
}
return this._docBase;
};
Evernote.NodeSerializer.prototype.getImagesUrls = function () {
return this._imagesUrls;
};
Evernote.NodeSerializer.prototype.getSerializedDom = function () {
return '<div style="position: relative;">' + this._serializedDom.replace(/[^\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD]+/g, "") + '</div>
';
};</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.SerializedNode = function SerializedNode( node, parent ) {
this.node = node;
this._parentSerializedNode = parent;
this.translateTo = [ ];
};
Evernote.SerializedNode.prototype.translateTo = null;
Evernote.SerializedNode.prototype.node = null;
Evernote.SerializedNode.prototype._parentSerializedNode = null;
Evernote.SerializedNode.prototype.setStyle = function ( clipStyle ) {
this._clipStyle = clipStyle;
};
Evernote.SerializedNode.prototype.getStyle = function () {
return this._clipStyle;
};
Evernote.SerializedNode.prototype.parentNode = function () {
return this._parentSerializedNode;
};
</script><script charset="ANSI" defer="" type="text/javascript">//"use strict";
Evernote.StylesCollection = function StylesCollection() {
this._styles = { };
};
Evernote.StylesCollection.prototype._styles = null;
Evernote.StylesCollection.prototype.addStyle = function( name, value, isImportant ) {
if ( typeof name == "string" && typeof value == "string" ) {
Evernote.Logger.debug( "StylesCollection.addStyle(): name = " + name + ", value = " + value + ", isImportant = " + isImportant );
this._styles[ name ] = new Evernote.ClipStyleProperty( name, value, isImportant);
}
};
Evernote.StylesCollection.prototype.getStyle = function( name ) {
if ( typeof name == "string" ) {
Evernote.Logger.debug( "StylesCollection.getStyle(): name = " + name + " value: " + ((typeof this._styles[ name ] != "undefined") ? this._styles[ name ].value() : null) );
return (typeof this._styles[ name ] != "undefined") ? this._styles[ name ].value() : null;
}
return null;
};
Evernote.StylesCollection.prototype.removeStyle = function( name ) {
if ( typeof name == "string" ) {
Evernote.Logger.debug( "StylesCollection.removeStyle(): name = " + name );
this._styles[ name ] = null;
delete this._styles[ name ];
}
};
Evernote.StylesCollection.prototype.isImportant = function( name ) {
if ( typeof name == "string" ) {
return (typeof this._styles[ name ] != "undefined") ? this._styles[ name ].isImportant() : false;
}
};
Evernote.StylesCollection.prototype.getStylesNames = function() {
Evernote.Logger.debug( "StylesCollection.getStylesNames()" );
var stylesNames = [ ];
for ( var key in this._styles ) {
if ( this._styles[ key ] != null ) {
stylesNames.push( key );
}
}
return stylesNames;
};
Evernote.StylesCollection.prototype.getStylesNumber = function() {
Evernote.Logger.debug( "StylesCollection.getStylesNumber()" );
var num = 0;
for ( var key in this._styles ) {
if ( this._styles[ key ] != null ) {
++num;
}
}
return num;
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.DataImageSerializer = function DataImageSerializer( node, nodeStyle ) {
if ( !nodeStyle ) {
nodeStyle = new Evernote.ClipStyle();
}
this.initialize( node, nodeStyle );
};
Evernote.inherit( Evernote.DataImageSerializer, Evernote.AbstractElementSerializer, true );
Evernote.DataImageSerializer.isResponsibleFor = function( node ) {
try {
if ( node && node.nodeType == Evernote.Node.ELEMENT_NODE && node.nodeName.toLowerCase() == "img" ) {
var src = node.getAttribute( "src" );
if ( src && src.indexOf( "data:image" ) != -1 ) {
return true;
}
}
} catch(e) {
Evernote.Logger.error("DataImageSerializer.isResponsibleFor failed due to error " + e);
}
return false;
};
Evernote.DataImageSerializer.prototype.serialize = function( /*docBase*/ ) {
Evernote.Logger.debug( "DataImageSerializer.serialize()" );
try {
this._nodeStyle.addStyle( { "background-image" : "url('" + this._node.getAttribute( "src" ) + "')",
"width" : this._node.offsetWidth + "px",
"height" : this._node.offsetHeight + "px",
"background-repeat" : "no-repeat",
"display" : "block" } );
return "<span style=\"" + this._nodeStyle.toString().replace( /"/g, "" ) + "\"" + "> </span>";
}
catch ( e ) {
Evernote.Logger.error( "DataImageSerializer.serialize() failed: error = " + e );
}
return "";
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.VideoElementSerializer = function VideoElementSerializer( node, nodeStyle ) {
this.initialize( node, nodeStyle );
};
Evernote.inherit( Evernote.VideoElementSerializer, Evernote.AbstractElementSerializer, true );
Evernote.VideoElementSerializer.isResponsibleFor = function( node ) {
return node && node.nodeType == Evernote.Node.ELEMENT_NODE && node.nodeName.toLowerCase() == "video";
};
Evernote.VideoElementSerializer.prototype.serialize = function( /*docBase*/ ) {
Evernote.Logger.debug( "VideoElementSerializer.serialize()" );
try {
var width = this._node.offsetWidth;
var height = this._node.offsetHeight;
var doc = this._node.ownerDocument;
var canvas = doc.createElement( "CANVAS" );
canvas.width = width;
canvas.height = height;
var context = canvas.getContext( "2d" );
context.drawImage( this._node, 0, 0, width, height );
var dataUrl = canvas.toDataURL( "image/png" );
context.clearRect( 0, 0, width, height );
this._nodeStyle.addStyle( { "background-image" : "url('" + dataUrl + "')",
"width" : width + "px",
"height" : height + "px",
"display" : "block" } );
return "<a style=\"" + this._nodeStyle.toString().replace( /"/g, "" ) + "\"" + "href='" + doc.defaultView.location.href + "'> </a>";
}
catch ( e ) {
Evernote.Logger.error( "VideoElementSerializer.serialize() failed: error = " + e );
}
return "";
};</script><script charset="ANSI" defer="" type="text/javascript">/**
* Serializes DOM element into an img pointing to the thumbnail of the video
*
* Video ids are used for obtaining thumbnails via
* https://i2.ytimg.com/vi/cAcxHQalWOw/hqdefault.jpg. These ids can be
* obtained from:
*
* <pre>
* - the URL of the document containing EMBED
* - iframe's src attribute that embeds the video via an iframe
* - src attribute of the embed object (though on actualy youtube.com it's not possible)
* </pre>
*
* Sample URLs are:
*
* <pre>
* http: //www.youtube.com/embed/IWJJBwKhvp4?wmode=opaque&rel=0
* http: //www.youtube.com/v/YZEbBZ2IrXE?version=3&rel=1&fs=1&showsearch=0&showinfo=1&iv_load_policy=1
* http: //www.youtube.com/v/J3mjFSTsKiM&hl=en&fs=1
* http://www.youtube.com/watch?v=cAcxHQalWOw
* http://www.youtube.com/user/IFiDieApp?v=sdzCELofGgE&feature=pyv
* </pre>
*/
Evernote.YoutubeElementSerializer = function YoutubeElementSerializer( doc, node, nodeStyle ) {
this.initialize( doc, node, nodeStyle );
};
Evernote.inherit( Evernote.YoutubeElementSerializer, Evernote.AbstractElementSerializer, true );
Evernote.YoutubeElementSerializer.WATCH_URL_REGEX = /^https?:\/\/www\.youtube\.com\/watch\?.*v=([^&]+)/i;
Evernote.YoutubeElementSerializer.USER_CHANNEL_URL_REGEX = /^https?:\/\/www\.youtube\.com\/user\/([a-zA-Z0-9]+)\?v=([^&]+)/i;
Evernote.YoutubeElementSerializer.EMBED_URL_REGEX = /^https?:\/\/www\.youtube\.com\/embed\/([^\/\?&]+)/i;
Evernote.YoutubeElementSerializer.VIDEO_URL_REGEX = /^https?:\/\/www\.youtube\.com\/v\/([^\/\?&]+)/i;
Evernote.YoutubeElementSerializer.POSSIBLE_CONTAINER_NODES = [ "OBJECT" ];
Evernote.YoutubeElementSerializer.VIDEO_NODES = [ "EMBED", "IFRAME" ];
Evernote.YoutubeElementSerializer.WATCH_URL = "http://www.youtube.com/watch?v=$videoId$";
Evernote.YoutubeElementSerializer.USER_CHANNEL_URL = "http://www.youtube.com/user/$userId$?v=$videoId$";
Evernote.YoutubeElementSerializer.DEFAULT_THUMB_URL = "https://i2.ytimg.com/vi/$videoId$/default.jpg";
Evernote.YoutubeElementSerializer.HQ_THUMB_URL = "https://i2.ytimg.com/vi/$videoId$/hqdefault.jpg";
Evernote.YoutubeElementSerializer.DEFAULT_THUMB_WIDTH = 120;
Evernote.YoutubeElementSerializer.DEFAULT_THUMB_HEIGHT = 90;
Evernote.YoutubeElementSerializer.isResponsibleFor = function( node ) {
var params = this.extractVideoParamsFromNode( node );
return (params) ? true : false;
};
Evernote.YoutubeElementSerializer.extractVideoParamsFromNode = function( node ) {
Evernote.Logger.debug( "YoutubeElementSerializer.extractVideoIdFromNode()" );
try {
if ( node && node.nodeType == Evernote.Node.ELEMENT_NODE ) {
var view = window;
try {
view = node.ownerDocument.defaultView;
}
catch ( e ) {
}
var matches = null;
if ( view && (node.nodeName.toLowerCase() == "embed" || node.nodeName.toLowerCase() == "object") && view.location ) {
if ( (matches = view.location.href.match( this.WATCH_URL_REGEX )) && matches[ 1 ] ) {
return matches[ 1 ];
}
else if ( (matches = view.location.href.match( this.USER_CHANNEL_URL_REGEX )) && matches[ 1 ] && matches[ 2 ] ) {
return [ matches[ 1 ], matches[ 2 ] ];
}
}
else {
var videoNode = this.findVideoNode( node );
if ( videoNode ) {
var src = videoNode.getAttribute( "src" );
if ( src && (matches = src.match( this.EMBED_URL_REGEX )) && matches[ 1 ] ) {
return matches[ 1 ];
}
else if ( src && (matches = src.match( this.VIDEO_URL_REGEX )) && matches[ 1 ] ) {
return matches[ 1 ];
}
}
}
}
} catch(e) {
Evernote.Logger.error("failed to YoutubeElementSerializer.extractVideoParamsFromNode due to error " + e);
}
return null;
};
Evernote.YoutubeElementSerializer.findVideoNode = function( node ) {
Evernote.Logger.debug( "YoutubeElementSerializer.findVideoNode()" );
if ( node && node.nodeType == Evernote.Node.ELEMENT_NODE ) {
if ( Evernote.ArrayExtension.indexOf(this.VIDEO_NODES, node.nodeName.toUpperCase() ) >= 0 ) {
return node;
}
else if ( Evernote.ArrayExtension.indexOf(this.POSSIBLE_CONTAINER_NODES, node.nodeName.toUpperCase() ) >= 0 ) {
try {
var it = node.ownerDocument.createNodeIterator( node, NodeFilter.SHOW_ELEMENT, null, false );
var next = null;
while ( next = it.nextNode() ) {
if ( Evernote.ArrayExtension.indexOf(this.VIDEO_NODES, next.nodeName.toUpperCase() ) >= 0 ) {
return next;
}
}
} catch(e) {
//We ignore exception here, because if node iterator is not supported, than we could skip old pages (not Youtube).
return null;
}
}
}
return null;
};
Evernote.YoutubeElementSerializer.prototype._imageUrl = "";
Evernote.YoutubeElementSerializer.prototype.serialize = function( /*docBase*/ ) {
Evernote.Logger.debug( "YoutubeElementSerializer.serialize()" );
try {
var userId = null;
var videoId = null;
var params = this.constructor.extractVideoParamsFromNode( this._node );
if ( params instanceof Array ) {
userId = params[ 0 ];
videoId = params[ 1 ];
}
else if ( typeof params == "string" ) {
videoId = params;
}
if ( videoId ) {
var thumbUrl = null;
var w = 0;
var h = 0;
if ( this._nodeStyle ) {
var view = window;
try {
view = this._node.ownerDocument.defaultView;
}
catch ( e ) {
}
var computedStyles = Evernote.ElementExtension.getComputedStyle( this._node, null, view );
w = parseInt( Evernote.StyleElementExtension.getPropertyValue(computedStyles, "width" ) );
w = (isNaN( w )) ? 0 : w;
h = parseInt( Evernote.StyleElementExtension.getPropertyValue(computedStyles, "height" ) );
h = (isNaN( h )) ? 0 : h;
if ( w < this.constructor.DEFAULT_THUMB_WIDTH || h < this.constructor.DEFAULT_THUMB_HEIGHT ) {
thumbUrl = this.getDefaultThumbnailUrl( videoId );
}
else {
thumbUrl = this.getHQThumbnailUrl( videoId );
}
}
else {
thumbUrl = this.getDefaultThumbnailUrl( videoId );
}
if ( thumbUrl ) {
var styleStr = (this._nodeStyle instanceof Evernote.ClipStyle) ? ("style=\"" + this._nodeStyle.toString() + "\"") : "";
var attrs = this._node.attributes;
var attrStr = "";
for ( var i = 0; i < attrs.length; ++i ) {
var attr = attrs[ i ];
if(Evernote.ClipRules.KEEP_NODE_ATTRIBUTES["a"][attr.name]) {
attrStr += attr.name;
if ( attr.value ) {
attrStr += "=" + attr.value;
}
attrStr += " ";
}
}
var href = ( userId ) ? this.getUserChannelUrl( userId, videoId ) : this.getWatchUrl( videoId );
var imgAttrStr = "";
if ( w && h ) {
var k = w / h;
// scale by height
if ( k > this.constructor.DEFAULT_THUMB_WIDTH / this.constructor.DEFAULT_THUMB_HEIGHT ) {
imgAttrStr += "height=\"" + h + "\"";
}
else { // scale by width
imgAttrStr += "width=\"" + w + "\"";
}
}
this._imageUrl = thumbUrl;
return "<a " + styleStr + " " + attrStr + " href=\"" + href + "\"><img src=\"" + thumbUrl + "\" " + imgAttrStr + "/></a>";
}
}
}
catch ( e ) {
Evernote.Logger.error( "YoutubeElementSerializer.serialize() failed: error = " + e );
}
return "";
};
Evernote.YoutubeElementSerializer.prototype.getDefaultThumbnailUrl = function( videoId ) {
return this.constructor.DEFAULT_THUMB_URL.replace( /\$videoId\$/, videoId );
};
Evernote.YoutubeElementSerializer.prototype.getHQThumbnailUrl = function( videoId ) {
return this.constructor.HQ_THUMB_URL.replace( /\$videoId\$/, videoId );
};
Evernote.YoutubeElementSerializer.prototype.getWatchUrl = function( videoId ) {
return this.constructor.WATCH_URL.replace( /\$videoId\$/, videoId );
};
Evernote.YoutubeElementSerializer.prototype.getUserChannelUrl = function( userId, videoId ) {
return this.constructor.USER_CHANNEL_URL.replace( /\$userId\$/, userId ).replace( /\$videoId\$/, videoId );
};
Evernote.YoutubeElementSerializer.prototype.getImageUrl = function() {
return this._imageUrl;
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.IEStylePropertiesMapping = {
_mapping : {
"background-attachment" : "backgroundAttachment",
"background-color" : "backgroundColor",
"background-image" : "backgroundImage",
"background-repeat" : "backgroundRepeat",
"background-position-x" : "backgroundPositionX",
"background-position-y" : "backgroundPositionY",
"border-bottom-color" : "borderBottomColor",
"border-bottom-style" : "borderBottomStyle",
"border-bottom-width" : "borderBottomWidth",
"border-left-color" : "borderLeftColor",
"border-left-style" : "borderLeftStyle",
"border-left-width" : "borderLeftWidth",
"border-right-color" : "borderRightColor",
"border-right-style" : "borderRightStyle",
"border-right-width" : "borderRightWidth",
"border-top-color" : "borderTopColor",
"border-top-style" : "borderTopStyle",
"border-top-width" : "borderTopWidth",
"border-collapse" : "borderCollapse",
"font-family" : "fontFamily",
"font-size" : "fontSize",
"font-style" : "fontStyle",
"font-weight" : "fontWeight",
"float" : "styleFloat",
"ime-mode" : "imeMode",
"letter-spacing" : "letterSpacing",
"line-height" : "lineHeight",
"list-style-image" : "listStyleImage",
"list-style-position" : "listStylePosition",
"list-style-type" : "listStyleType",
"margin-bottom" : "marginBottom",
"margin-left" : "marginLeft",
"margin-right" : "marginRight",
"margin-top" : "marginTop",
"max-height" : "maxHeight",
"max-width" : "maxWidth",
"min-height" : "minHeight",
"min-width" : "minWidth",
"overflow-x" : "overflowX",
"overflow-y" : "overflowY",
"padding-bottom" : "paddingBottom",
"padding-left" : "paddingLeft",
"padding-right" : "paddingRight",
"padding-top" : "paddingTop",
"page-break-after" : "pageBreakAfter",
"page-break-before" : "pageBreakBefore",
"table-layout" : "tableLayout",
"text-align" : "textAlign",
"text-decoration" : "textDecoration",
"text-indent" : "textIndent",
"text-overflow" : "textOverflow",
"text-transform" : "textTransform",
"vertical-align" : "verticalAlign",
"white-space" : "whiteSpace",
"word-spacing" : "wordSpacing",
"word-wrap" : "wordWrap",
"z-index" : "zIndex"
},
getPropertyNameFor: function(styleName) {
return [styleName, this._mapping[styleName]];
},
getPropertiesList: function() {
return this._mapping;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.StylesReplacementRegistry = {
registry: [],
getImplementationFor: function(name) {
if(name) {
return this.registry[name];
}
return null;
},
register: function(name, impl) {
this.registry[name] = impl;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.FontSizeReplacement = {
SUPPORTED_FONT_SIZES: ["em", "%", "pt", "px"],
getValue: function(val) {
if(typeof val != "string")
return val;
if(this.isCalculationRequired(val)) {
return Evernote.Utils.getFontSizeInPixels(val) + "px";
} else {
//Do not set browser dependant CSS since it does not supported by Evernote Chromium Viewer.
return null;
}
},
isCalculationRequired: function(val) {
for(var i = 0; i < this.SUPPORTED_FONT_SIZES.length; i++) {
if(val.indexOf(this.SUPPORTED_FONT_SIZES[i]) != -1) {
return true;
}
}
return false;
}
};
Evernote.StylesReplacementRegistry.register("font-size", Evernote.FontSizeReplacement);</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ClipperElementsIdentifiers = {
_clipperElementsIds : [Constants.CLIP_DIALOG_ID, Constants.OPTIONS_DIALOG_ID],
match: function(node) {
if(node && node.id) {
var position = Evernote.ArrayExtension.indexOf(this._clipperElementsIds, node.id);
if(position) {
return position != -1;
}
}
return false;
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.NotebooksLoader = {
notebooks: [],
getNotebookByUid: function(uid) {
Evernote.ResponseReceiver.subscribe(this);
Evernote.Addin.getNotebooks(document);
for(var i = 0; i < this.notebooks.length; i++) {
if(this.notebooks[i].uid == uid) {
return this.notebooks[i];
}
}
return null;
},
onDataReceived: function(response) {
if(response.type) {
if(response.type == "notebooks") {
this.notebooks = this.notebooks.concat(response.data);
}
}
}
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Notebook = function(type, name, uid, stack, author, hidden) {
this.type = type;
this.name = name;
this.uid = uid;
this.stack = stack;
this.author = author;
this.hidden = hidden;
};
</script><script charset="ANSI" defer="" type="text/javascript">Evernote.Tag = function(name, uid) {
this.name = name;
this.uid = uid;
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.NotebookTypes = {
PERSONAL: 1,
BUSINESS: 2,
LINKED: 3
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.ErrorCodes = {
AUTHENTICATION_ERROR: "LoginFailure",
CLIP_ERROR: "NoteImportFailure"
};</script><script charset="ANSI" defer="" type="text/javascript">Evernote.AuthenticatedException = function(msg){
this.msg = msg;
this.code = Evernote.ErrorCodes.AUTHENTICATION_ERROR;
};</script><script charset="ANSI" defer="" type="text/javascript">try {
Evernote.Addin.init(EvernoteExternal.Addin);
Evernote.Addin.resetAuthenticatedState();
Evernote.FS.init(EvernoteExternal.Addin);
Evernote.Logger = Evernote.LoggerConfigurator.getLogger();
if(!Evernote.JQuery)
Evernote.JQueryLoader.initJQuery();
window.jQueryForClearlyComponent = Evernote.JQuery;
initClearly(window);
if(Evernote.evernotePopup) {
Evernote.evernotePopup.hide();
}
Evernote.Logger.debug("Init EnClipper");
Evernote.EnClipper.init();
Evernote.Logger.debug("EnClipper initialized");
Evernote.pageInfo = new PageInfo();
Evernote.contentPreviewer = new ContentPreview();
Evernote.Options.load();
if (EvernoteExternal.Addin.isServerAvailable()) {
Evernote.Clipper.clipWithOptions(EvernoteExternal.clipOptions);
}
} catch(e) {
alert("Failed to clip via context menu" + e);
throw e;
}</script><style id="_clearly_component__css" type="text/css"></style><br />
<div id="_clearly_component__next_pages_container">
</div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-52513350166249399632013-11-19T17:21:00.000-07:002013-11-19T17:21:14.364-07:00Back to a Balanced Market
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Buyer’s Market, Seller’s Market, Balanced Market.<span style="mso-spacerun: yes;"> </span>At times the circumstances of the real estate
market will provide advantages to the buyer, advantages to the seller, or
relatively equal advantages to the buyer and seller.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Buyer’s Market<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">In the aftermath of the financial crisis and bursting of the
real estate bubble there was considerable advantages for buyers.<span style="mso-spacerun: yes;"> </span>First, there were fewer buyers as many people
were negatively impacted by the economy and weren’t in a financial position to
purchase a home.<span style="mso-spacerun: yes;"> </span>Also, there was excess
inventory as the construction of homes had exceeded demand, and a glut of
foreclosures added to the homes that needed to be sold.<span style="mso-spacerun: yes;"> </span>So the result was a few years of very
depressed prices, which combined with low interest rates made the buying
opportunity of a lifetime.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Seller’s Market<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">As folks began to recover from their economic woes, there
were more potential buyers in the market.<span style="mso-spacerun: yes;">
</span>Low interest rates leveraged their buying power.<span style="mso-spacerun: yes;"> </span>Since very few homes had been constructed
since the recession, the trends of the market started to reverse.<span style="mso-spacerun: yes;"> </span>The growing pool of potential buyers didn’t
have enough homes available to fulfill their demand, and prices began to
increase.<span style="mso-spacerun: yes;"> </span>Sellers found themselves in a
good bargaining position and buyers had to compete for homes, resulting in
bidding wars.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<b style="mso-bidi-font-weight: normal;"><span style="font-family: Calibri;">Balanced Market<o:p></o:p></span></b></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The market appears to be in a more balanced position
today.<span style="mso-spacerun: yes;"> </span>Inventory is more adequate as
builders are constructing more homes than they were in prior years.<span style="mso-spacerun: yes;"> </span>Sellers’ equity positions have improved with
rising prices; putting them in a better position to be able to sell their homes
and benefit financially.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f"><span style="font-family: Calibri;">
<v:stroke joinstyle="miter">
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0">
<v:f eqn="sum @0 1 0">
<v:f eqn="sum 0 0 @1">
<v:f eqn="prod @2 1 2">
<v:f eqn="prod @3 21600 pixelWidth">
<v:f eqn="prod @3 21600 pixelHeight">
<v:f eqn="sum @0 0 1">
<v:f eqn="prod @6 1 2">
<v:f eqn="prod @7 21600 pixelWidth">
<v:f eqn="sum @8 21600 0">
<v:f eqn="prod @7 21600 pixelHeight">
<v:f eqn="sum @10 21600 0">
</v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:formulas>
<v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f">
<o:lock aspectratio="t" v:ext="edit">
</o:lock></v:path></v:stroke></span></v:shapetype><span style="font-family: Calibri;">Some
buyers might complain that prices are higher and they missed out of the great
bargains of the recession.<span style="mso-spacerun: yes;"> </span>Yes, a buyer
could have picked up some great deals in 2010 and 2011, and would be enjoying
some substantial value increases today.<span style="mso-spacerun: yes;">
</span>But the past is the past.<span style="mso-spacerun: yes;"> </span>Unless
you have a DeLorean with a flux capacitor you need to live in the present.</span></div>
<span style="font-family: Calibri;"><div class="separator" style="clear: both; margin: 0in 0in 10pt; text-align: right;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqR1xVZDvYg-YQqI9GNiHSgLpI6qOf3WwjoQcPmKOFmf6LuOpA9z1PoBfgRtAhqpN7SO6BqVhcWkfAXXgv_g-pOh8oDzh6NVIw_39x8moiyW2FAdxgfOTu3bLT-32N4RpwIoBQnZBLWP8/s1600/delorean.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="229" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqR1xVZDvYg-YQqI9GNiHSgLpI6qOf3WwjoQcPmKOFmf6LuOpA9z1PoBfgRtAhqpN7SO6BqVhcWkfAXXgv_g-pOh8oDzh6NVIw_39x8moiyW2FAdxgfOTu3bLT-32N4RpwIoBQnZBLWP8/s320/delorean.jpg" width="320" /></a></div>
</span><div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">The present balanced market is good for homebuyers.<span style="mso-spacerun: yes;"> </span>They have more homes to choose from than they
did just a year ago, and the bidding wars that took place in the seller’s
market are much less frequent.<span style="mso-spacerun: yes;"> </span>Buyers
also are enjoying the extra buying power that comes with very low interest
rates.<span style="mso-spacerun: yes;"> </span>A 1% increase in rate equates to
an increase in price (based on relative payment) of 10% to 13%.<span style="mso-spacerun: yes;"> </span>So today’s rate environment is like a blue
light special on houses.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri;">Today’s potential buyers shouldn’t be frustrated that home
prices have increased.<span style="mso-spacerun: yes;"> </span>They are still
well below the highs of the last decade.<span style="mso-spacerun: yes;">
</span>There are more homes to choose from, and low fixed interest rates give homebuyers
tremendous purchasing power. <o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-54470557914821463552013-11-12T10:45:00.000-07:002014-02-04T16:15:09.230-07:00Impact of “Qualified Mortgage” Rule on Homebuyers<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<b style="mso-bidi-font-weight: normal;"><span style="color: black; font-family: "Arial","sans-serif";"><o:p></o:p></span></b> </div>
<span style="color: black; font-family: "Arial","sans-serif";">The
Dodd-Frank Wall Street Reform Act of 2010 requires the creation and
implementation of 398 rules.<span style="mso-spacerun: yes;"> </span>That is
quite a hefty meal for lenders to digest.<span style="mso-spacerun: yes;">
</span>As of September 2013, only 160 of those rules (slightly over 40%) have
been finalized.<span style="mso-spacerun: yes;"> </span>There are a couple of those
rules going into effect on January 10, 2014 as a result of Dodd-Frank that are
impactful to homebuyers. <o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"><o:p> </o:p></span></div>
<span style="color: black; font-family: "Arial","sans-serif";">The
mortgage industry already felt the effect of a number of rules from this law,
but there are more rules coming soon, and those won't be the last either.
The Act requires that lenders “must make a reasonable and good faith
determination based on verified and documented information that the consumer
has a reasonable ability to repay the loan according to its terms.”<span style="mso-spacerun: yes;"> </span>It also establishes a “Safe Harbor” and
presumption of compliance for a certain category called “Qualified
Mortgages.”<span style="mso-spacerun: yes;"> </span>Of course the lending
industry should make sure borrowers can repay the loan.<span style="mso-spacerun: yes;"> </span>That is common sense, and the way the
industry has operated since “no doc” loans went extinct over five years
ago.<span style="mso-spacerun: yes;"> </span>The law and accompanying
regulations have the purpose of ensuring that those risky loans don’t come back
to life. <span style="mso-spacerun: yes;"> </span>So what is really changing on
January 10?<span style="mso-spacerun: yes;"> </span>Basically, lenders have to
document that loans meet the characteristics of “Qualified Mortgages” if they
want to be protected from litigation.<o:p></o:p></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ58Sloq5d08JGy8jUwcG0yTMxo6cBxHe8mgKQt99_vbTUu3WFDMtQBjYLefXZzZg1oDlj5MIAz7Y4QYYLU8XwZ_FIhGvSyO52zH2GMAhmDiceOSbyfXUy8gjrnG8fMQVtMrqvrdNGjD8/s1600/Keep+Calm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ58Sloq5d08JGy8jUwcG0yTMxo6cBxHe8mgKQt99_vbTUu3WFDMtQBjYLefXZzZg1oDlj5MIAz7Y4QYYLU8XwZ_FIhGvSyO52zH2GMAhmDiceOSbyfXUy8gjrnG8fMQVtMrqvrdNGjD8/s1600/Keep+Calm.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: right;">
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"><o:p> </o:p></span></div>
<span style="color: black; font-family: "Arial","sans-serif";">Mortgage
firms are working tirelessly on implementing plans to be compliant ahead of the
January 10 deadline. This includes integrating new technology into the
process, fine-tuning processes to ensure only compliant loans are originated,
updating documents, and modifying or potentially eliminating loan products that
will not meet QM rules.<o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"><o:p> </o:p></span></div>
<b><span style="color: black; font-family: "Arial","sans-serif";">Qualified
Mortgages (QM)<o:p></o:p></span></b><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";">Under
the QM Rules, loans generally cannot contain risky features (i.e., interest
only, negative amortization or balloon payments), and the loan term cannot
exceed 30 years. Points and fees are limited to 3% for loans of $100,000 or
more (higher thresholds are permitted for loans below $100,000). In addition,
for most QM loans, Debt-to-Income (DTI) ratio is limited to 43%. The max DTI
does not apply to Fannie, Freddie, FHA, VA, or USDA eligible loans that have a
valid automated underwriting system approval. There is no minimum down
payment requirement for QM.<span style="mso-spacerun: yes;"> </span>Within QM is
a requirement that the lender make certain the borrower has the ability to
repay the loan.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"> <o:p></o:p></span></div>
<b><span style="color: black; font-family: "Arial","sans-serif";">Ability
to Repay (ATR)</span></b><span style="color: black; font-family: "Arial","sans-serif";"> <o:p></o:p></span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";">ATR
focuses on underwriting practices and requires lenders to consider a borrower’s
ability to repay the mortgage before extending credit to the borrower. The ATR
Rule establishes minimum standards (</span><a href="http://files.consumerfinance.gov/f/201301_cfpb_ability-to-repay-summary.pdf"><span style="font-family: "Arial","sans-serif";"><span style="color: blue;">eight specific factors</span></span></a><span style="color: black; font-family: "Arial","sans-serif";">) for lenders to use in
determining whether consumers have the ability to repay the mortgage. Loans
that meet the QM standard (discussed above) are presumed to be compliant with
the ATR Rule. Non-QM loans can still meet the ATR Rule standards, but must be
separately underwritten with the specific ATR factors in mind.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"><o:p> </o:p></span></div>
<b style="mso-bidi-font-weight: normal;"><span style="color: black; font-family: "Arial","sans-serif";">Safe Harbor<o:p></o:p></span></b><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";">QM
loans that are not “higher-priced” under the Rule have a “safe harbor.” This
means that these loans are conclusively presumed to comply with the ATR
requirements.<span style="mso-spacerun: yes;"> </span>Higher-priced loans that
meet the QM criteria are also presumed to be compliant with the ATR Rule; however,
a consumer may rebut this presumption in a lawsuit. A first-lien mortgage loan
is considered “higher-priced” if the APR is 1.5 percentage points or more over
the Average Prime Offer Rate <o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";">(APOR).
This “safe harbor” provides some added level of legal protection for lenders
defending ability to repay lawsuits.<span style="mso-spacerun: yes;"> </span><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";"> <o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="color: black; font-family: "Arial","sans-serif";">Here
are some areas of potential impact:<o:p></o:p></span></div>
<br />
<ul type="disc">
<li class="MsoNormal" style="color: black; margin: 0in 0in 0pt; mso-list: l0 level1 lfo1; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; tab-stops: list .5in;"><span style="font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">Programs with
"risky features" such as interest only, balloon payments, and
terms longer than 30 years will not meet the QM rule.<o:p></o:p></span></li>
<li class="MsoNormal" style="color: black; margin: 0in 0in 0pt; mso-list: l0 level1 lfo1; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; tab-stops: list .5in;"><span style="font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">Mortgage
brokers will have a harder time meeting the max 3% points and fees as the
broker compensation is included in the calculation.<span style="mso-spacerun: yes;"> </span>Mortgage brokers will find it harder to
compete and be profitable with this new rule.<o:p></o:p></span></li>
<li class="MsoNormal" style="color: black; margin: 0in 0in 0pt; mso-list: l0 level1 lfo1; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; tab-stops: list .5in;"><span style="font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">Upfront Mortgage
Insurance (MI) on conforming loans is included in the max 3% points and
fees calculation unless it is refundable. Refundable MI policies
will carry a higher premium than non-refundable policies. Still any
amount of the refundable premium that is above the FHA upfront premium
must be included in the calculation.<o:p></o:p></span></li>
<li class="MsoNormal" style="color: black; margin: 0in 0in 0pt; mso-list: l0 level1 lfo1; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; tab-stops: list .5in;"><span style="font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">For Adjustable
Rate Mortgage (ARM) products, the 43% maximum debt-to-income ratio (DTI)
is calculated based on the highest possible rate in the first 5 years of
the term.<o:p></o:p></span></li>
<li class="MsoNormal" style="margin: 0in 0in 0pt; mso-list: l0 level1 lfo1; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; tab-stops: list .5in;"><span style="color: black; font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">Allowing
Fannie & Freddie loans to exceed the max 43% DTI with a valid AUS
approval only applies while the GSE's are
under conservatorship of the Federal government</span><span style="font-family: "Arial","sans-serif"; mso-fareast-font-family: "Times New Roman";">.
The good news is that they will likely stay in control of the government
for at least several years as there is no clear plan to wind them down.<o:p></o:p></span></li>
</ul>
<br />
<div class="MsoNormal" style="margin: 0in 0in 0pt;">
<span style="font-family: "Arial","sans-serif";">In principal
the concept of documenting a borrower’s ability to repay a loan was already
addressed by the market over five years ago.<span style="mso-spacerun: yes;">
</span>Lenders with any memory of the financial crisis are not going to offer
“no doc” loan products again; however, the law is designed to ensure that
lenders can’t offer them ever again.<span style="mso-spacerun: yes;">
</span>Lenders will want the majority, if not all, of their loans to fall into the
“safe harbor.”<span style="mso-spacerun: yes;"> </span>This will lead to a
greater workload that burdens lenders, but it should have minimal impact on
consumers’ ability to obtain a home loan. <o:p></o:p></span></div>
Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com0tag:blogger.com,1999:blog-1109187777803058794.post-4345162356037986032012-01-10T19:11:00.003-07:002012-01-10T19:26:56.486-07:00Mortgage Insurance Tax Deduction Out<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN2TC-R32NsPQSkRDk_zMZDNXAzX0zflvprGUU2XDM-3wFjbVpd9378OogAY_rNb5eJyd4pDqUO0IyupKikzjHspgPFtdQLZrG4wtK35gdQI1xLUmih59Jh05T3rCKBLb6tEbIh-JD4mY/s1600/mortgage_premium_protection.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN2TC-R32NsPQSkRDk_zMZDNXAzX0zflvprGUU2XDM-3wFjbVpd9378OogAY_rNb5eJyd4pDqUO0IyupKikzjHspgPFtdQLZrG4wtK35gdQI1xLUmih59Jh05T3rCKBLb6tEbIh-JD4mY/s200/mortgage_premium_protection.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5696194910553105362" /></a><br />In the process of haggling over a 2 month extension of the payroll tax reduction (which is increasing mortgage rates, see my Dec 30, 2011 posting), Congress failed to extend a number of existing tax deductions. One of those deductions that is no longer in effect is the deduction for mortgage insurance.<div><br /></div><div>When a home buyer puts less than 20% as a down payment, they have to pay a mortgage insurance premium. Mortgage insurance is a policy that pays the lender a claim in the event a borrower defaults on the loan. Up until midnight on New Years Eve, that premium was tax deductible.</div><div><br /></div><div>Congress may extend the deduction and make it retroactive to the beginning of the year. But many of the tax deductions are considered bad policy by tax experts and may not be in favor. So for the time being, mortgage insurance is not a tax deduction.</div>Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com8tag:blogger.com,1999:blog-1109187777803058794.post-24867490421092749122011-12-30T13:59:00.003-07:002011-12-30T14:07:08.902-07:00Payroll Tax Cut Paid for with Higher Mortgage RatesThe Temporary Payroll Tax Cut Continuation Act of 2011 was signed into law earlier this month. At the time it was passed we knew it was going to be financed with higher guaranty fees from Fannie Mae & Freddit Mac. These G-Fees are built into the price or interest rate of a new home loan. Today, Fannie Mae announced that they are raising their G-Fees by 10 basis points (0.1%) beginning April 1.<br /><br />What this means for those looking to finance the purchase of a home, or refinancing, is that they will pay about 0.1% higher in interest rate than they otherwise would have. Lenders' rates will be impacted a couple months in advance of the April 1 start date.<br /><br />So a payroll tax cut is paid for by what amounts to a mortgage tax for new homeowners and those that refinance their existing home loans.Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com4tag:blogger.com,1999:blog-1109187777803058794.post-2024764006159411972011-12-02T12:21:00.003-07:002011-12-02T13:04:29.683-07:00Too Difficult to do Mortgages in Massachusetts<div><div>I just received this notice from GMAC who is one of the investors that we sell mortgages to. </div><div><br /><em>"GMAC Bank (GMACB) Correspondent Funding Approved Correspondent Clients<br />please note that effective Tuesday, December 6, 2011, GMACB will no longer<br />accept new locks for properties located in the Commonwealth of Massachusetts.<br />This change is necessary due to the complexity of transacting business in an<br />increasingly difficult legal environment in Massachusetts."<br /></em></div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgirGzf0vCyDp7cCT3fE9wIUUGT8CYnRrerjQi7YnbVlQ4aQqcYFWQDjcutUc7MgbzMUSMlMZc_gK3ErL9c_w0A0KCJhGttL1dj3WimHK294aivPa86QR7AyrvGvifhDooEPzANjo4pnrg/s1600/massachusetts.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="margin: 0px 10px 10px 0px; width: 200px; height: 164px; float: left; cursor: pointer;" id="BLOGGER_PHOTO_ID_5681623798440490802" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgirGzf0vCyDp7cCT3fE9wIUUGT8CYnRrerjQi7YnbVlQ4aQqcYFWQDjcutUc7MgbzMUSMlMZc_gK3ErL9c_w0A0KCJhGttL1dj3WimHK294aivPa86QR7AyrvGvifhDooEPzANjo4pnrg/s200/massachusetts.jpg" /></a>Politicians in Massachusetts and other states need to understand that overly burdensome legislation and regulation on banks and mortgage companies will ultimately hurt the people for whom they are there to serve.</div></div>Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com4tag:blogger.com,1999:blog-1109187777803058794.post-25723666340846687962011-11-29T12:00:00.005-07:002011-11-29T12:15:06.850-07:00HARP Part Deux<div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEnY4Cg4SKrs0CVexUcorE9zqXWIWHSoqaMkJVRc1QDg01akjGnTI9AiILTda8v3zg5paQW8wV9rtqtYnDtHUr-Gkri25HvBw8e86Y7Awww7m0CPJ8qCUDY79nP0RnoMGLYLx_SFXF0ZM/s1600/American-Gothic-House-Underwater--31269.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="margin: 0px 0px 10px 10px; width: 138px; height: 200px; float: right; cursor: pointer;" id="BLOGGER_PHOTO_ID_5680497483846279026" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEnY4Cg4SKrs0CVexUcorE9zqXWIWHSoqaMkJVRc1QDg01akjGnTI9AiILTda8v3zg5paQW8wV9rtqtYnDtHUr-Gkri25HvBw8e86Y7Awww7m0CPJ8qCUDY79nP0RnoMGLYLx_SFXF0ZM/s200/American-Gothic-House-Underwater--31269.jpg" /></a><br /><div>Refinance to a lower interest rate, even if you are infinitely underwater on your mortgage. As long as the homeowner has continued to make the payment on time, this is part of the newly enhanced Home Affordable Refinance Program. The previous guidelines limited loan amounts on HARP refinances to 125% of the current appraised value. Removing that guideline opens the door to many homeowners that owe significantly more than their property is worth.</div><div> </div><div>Here are some important points about the program:</div><ul><li>Mortgage must currently be owned by Fannie Mae or Freddie Mac</li><li>Mortgages must have been acquired by Fannie or Freddie prior to May 31, 2009</li><li>Fannie & Freddie roll out the new guidelines on December 1, but it will take lenders a couple of months to implement the program.</li><li>Program ends December 31, 2013.</li></ul><p>Please contact me directly with questions related to refinancing under HARP. <a href="mailto:cmozilo@homeownersfg.com">cmozilo@homeownersfg.com</a></p><p> </p><div> </div></div>Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1tag:blogger.com,1999:blog-1109187777803058794.post-57947993855446096602011-10-16T18:55:00.008-07:002011-10-16T19:47:27.989-07:00Why Aren't Mortgage Rates Lower?<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJhj0GyZs7NsCp47deE9Ypu9Ld5RYFf2qvi_VssHq7Q-cF3wi5amcKPw6bEdhsB4GyIPqSMhXpYKfvAMipFvDMeF6Gz_N6nFpHuNXb6A_D6l9Cmpt8cnp5Nrycf7uAC9Yn0nZ9Y_PjShY/s1600/Federal_Reserve.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 153px; height: 115px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJhj0GyZs7NsCp47deE9Ypu9Ld5RYFf2qvi_VssHq7Q-cF3wi5amcKPw6bEdhsB4GyIPqSMhXpYKfvAMipFvDMeF6Gz_N6nFpHuNXb6A_D6l9Cmpt8cnp5Nrycf7uAC9Yn0nZ9Y_PjShY/s200/Federal_Reserve.jpg" alt="" id="BLOGGER_PHOTO_ID_5664284666642720210" border="0" /></a><br /><div style="text-align: left;">Mortgage rates are very low, historically speaking. But they are also high, historically speaking. Allow me to explain why that is not a contradiction.<br /><br /></div>The Federal Reserve has made it a priority to try to keep mortgage rates low. This is one of several strategies to stimulate the languishing economy. Starting in 2008 the Fed lowered short term rates to zero (or close to it). Then over the past year or two it purchased voluminous amounts of Treasury debt and mortgage backed securities. More recently the Fed has sold short term Treasury notes (with maturities of three years or less) and purchased long term Treasury debt in a plan coined, "Operation Twist." The Fed has also reinvested money from the early payoff of mortgages into new mortgage backed securities. That should help to <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguGqs7LzSJ-pBfGrBMwpF-PAaFIzxPlJajBdh6SVrMpjO8MJaUUngmkAliRXCxu4uK5YPOobzud9zBZ6PPJrdd1EvgmwzpLjv_sN6RDvhL1_81Yrq-R6x4hyphenhyphenvxcZ9OQMkxknZwI7VVG0Y/s1600/twister_cover.jpg"><img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 160px; height: 127px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguGqs7LzSJ-pBfGrBMwpF-PAaFIzxPlJajBdh6SVrMpjO8MJaUUngmkAliRXCxu4uK5YPOobzud9zBZ6PPJrdd1EvgmwzpLjv_sN6RDvhL1_81Yrq-R6x4hyphenhyphenvxcZ9OQMkxknZwI7VVG0Y/s200/twister_cover.jpg" alt="" id="BLOGGER_PHOTO_ID_5664285662868659362" border="0" /></a>lower the yields on those securities and therefore the rates on the loans those securities are backed by.<br /><br />Treasury rates and mortgage rates typically move in step. I've written about that many times. Back in February the spread between a 10 year Treasury and a 30 mortgage was only 128 basis points (1 basis point is 1/100th of one percent). As of last week that spread has increased to 199 basis points. The work the Fed has done should lower mortgage rates as the Treasury rates have fallen. But mortgages seem to be more expensive than they have been in the past relative to Treasuries. Why?<br /><br /><span style="font-weight: bold;">Fewer Loan Originators</span><br />One reason is that there are fewer loan originators than there have been in the past. There are fewer mortgage companies as many did not survive the financial meltdown. Also the mortgage broker segment (small companies that originated home loans and delivered them to wholesale lenders) has lost over 100,000 brokers since 2006. As rates drop it is more difficult for new loan originators to get into the industry to service the demand due to licensing requirements that went into effect last year in all fifty states.<br /><br /><span style="font-weight: bold;">Tighter Underwriting Guidelines</span><br />There are tougher requirements to get a loan today. A mortgage company only earns income on loans that close. Since more loans are cancelled or declined in process that creates extra expense <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrnse8Ntws1rGHxKy_eD7FgLZDOiO3DbM99sIZ7-o0_ontju7jaRY_I2xU7qjsbXL72na8JryhXfgFczee0sV1I7wr5uHvY9cWjQvSnazULlQxcJp_H7iyd6kapTMAj1j8DqiNA9tVtGs/s1600/mortgage-denied.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 151px; height: 122px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrnse8Ntws1rGHxKy_eD7FgLZDOiO3DbM99sIZ7-o0_ontju7jaRY_I2xU7qjsbXL72na8JryhXfgFczee0sV1I7wr5uHvY9cWjQvSnazULlQxcJp_H7iyd6kapTMAj1j8DqiNA9tVtGs/s200/mortgage-denied.jpg" alt="" id="BLOGGER_PHOTO_ID_5664286438503854706" border="0" /></a>for lenders without any offsetting income. Therefore the cost per loan rises and that expense is spread out among the loans that do close.<br /><br /><span style="font-weight: bold;">Compliance & Regulation</span><br />As a result of the real estate collapse and the financial meltdown new laws and regulation have been an albatross for mortgage companies. To avoid penalties lenders have to spend extra time and hire additional personnel solely for the purpose of ensuring customer disclosures and re-disclosures are accurate. In addition, rules concerning loan originator compensation that were born out of the Dodd-Frank Wall Street Reform Act have actually hampered loan originators' ability to compete and lower fees for their customers.<br /><br /><span style="font-weight: bold;">"Too Big to Fail" Got Bigger</span><br />The top five lenders control 65% of loan production, and they don't seem very interested to compete on rate. In fact, the limited capacity of a few major players encourages them to simply increase their profit margins as demand rises.<br /><br />Rates are very low, and there are incredible opportunities to finance the purchase of a home or refinance. But these are the reasons why rates are not even lower than what they are.Chris Mozilo, CMBhttp://www.blogger.com/profile/15901613718874544214noreply@blogger.com1