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 // // <![CDATA[
/*! 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("”).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?””:””)+””),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(;e0){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=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\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^(?:)?$/,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.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(;j0)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;f0&&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(;b1?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=d1){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="
a“,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!==””,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=”
// 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, ‘ ‘)) ”); else
{
// if all else failed, get document title
// ======================================
// loop through pregs
// ==================
for (var i=0, _i=_doc_title_pregs.length; i 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 1 ? _doc_title_parts[0] : _documentTitle)
+ $R.articleTitleMarker__end
// 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 ”)):
case (_element.tagName.toLowerCase() == ‘onject’):
case (_element.tagName.toLowerCase() == ’embed’):
return;
}
$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;
};
}
// 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 -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 -1)
{ _result._is__image_skip = true; 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(); }
$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;
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 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]); }
// 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 250)
;
// negative
if (_points_history[0] 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;
default: return 0;
}
});
// second candidate computation
// ============================
for (var i=0, _i=_candidates.length; i 0.05)):
case (!(_candidates[i][‘__candidate_details_second’][‘_ratio__length__plain_text_to_total_plain_text’] > 0.05)):
// 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);
// 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; }
// 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 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 ”)
{ _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 -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 += ”;
/* 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
// actually do it
_recursive(_nodeToBuildHTMLFor);
// return html
return _global__the_html;
};
// article title marker
// ====================
$R.articleTitleMarker__start = ‘
‘;
$R.articleTitleMarker__end = ‘
‘;
// 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 = [
/]*?>([\s\S]+?)/gi,
/]*?>([\s\S]+?)/gi,
/]*?>([\s\S]+?)/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 -1)):
// will continue loop
break;
// return?
switch (true)
{
case (!(_heading_length > 5)):
case (!(_heading_length < (65 * 3))):
case (!(_to_heading_length -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 -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 ” ? $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?
// ======================
// 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, ‘ ‘)) ”); else
{
// if all else failed, get document title
// ======================================
// loop through pregs
// ==================
for (var i=0, _i=_doc_title_pregs.length; i 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 1 ? _doc_title_parts[0] : _documentTitle)
+ $R.articleTitleMarker__end
// 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’);
}
var _caption2 = ”;
for (var i=0, _i=_caption.length, _code=0; i 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; } }
// sort — the less points, the closer to position 0
// ====
_links.sort(function (a, b)
{
switch (true)
{
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,
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;
}
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.
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 // <![CDATA[
/*mousewheel*/
(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[–c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[–a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[–a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
/*custom scrollbar*/
(function(c){var b={init:function(e){var f={set_width:false,set_height:false,horizontalScroll:false,scrollInertia:950,mouseWheel:true,mouseWheelPixels:"auto",autoDraggerLength:true,autoHideScrollbar:false,alwaysShowScrollbar:false,snapAmount:null,snapOffset:0,scrollButtons:{enable:false,scrollType:"continuous",scrollSpeed:"auto",scrollAmount:40},advanced:{updateOnBrowserResize:true,updateOnContentResize:false,autoExpandHorizontalScroll:false,autoScrollOnFocus:true,normalizeMouseWheelDelta:false},contentTouchScroll:true,callbacks:{onScrollStart:function(){},onScroll:function(){},onTotalScroll:function(){},onTotalScrollBack:function(){},onTotalScrollOffset:0,onTotalScrollBackOffset:0,whileScrolling:function(){}},theme:"light"},e=c.extend(true,f,e);return this.each(function(){var m=c(this);if(e.set_width){m.css("width",e.set_width)}if(e.set_height){m.css("height",e.set_height)}if(!c(document).data("mCustomScrollbar-index")){c(document).data("mCustomScrollbar-index","1")}else{var t=parseInt(c(document).data("mCustomScrollbar-index"));c(document).data("mCustomScrollbar-index",t+1)}m.wrapInner("
//
(function($){
//feature detection
var hasPlaceholder = ‘placeholder’ in document.createElement(‘input’);
var placeholderClass = ‘evn-placeholder’;
//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 , or make a new one from the Date
inputId = (this.id) ? this.id : ‘placeholder’ + (+new Date()) + this.className.replace(‘ ‘,”),
placeholderText = options.placeholderText ? options.placeholderText : $this.attr(‘placeholder’),
placeholder = $(”+ placeholderText + ”);
//stuff in some calculated values into the placeholderCSS object
// options.placeholderCSS[‘width’] = inputWidth;
options.placeholderCSS[‘height’] = inputHeight;
// return — will get [0] as the actual final points
// ======
return _points_history;
};
$D.getContent__processCandidates__first = 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;
default: return 0;
}
});
// get first
// =========
var _main = _candidates[0]
if ($D.debug) { $D.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 0) { continue; }
if ($CJ.contains(_candidates[i].__node, _candidates[k].__node)); else { continue; }
// store piece, if in debug mode
if ($D.debug) { _array__pieces.push(_candidates[k]); }
// 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 0)):
case (!($CJ.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;
default: return 0;
}
});
// second candidate computation
// ============================
for (var i=0, _i=_candidates.length; i 0.05)):
case (!(_candidates[i][‘__candidate_details_second’][‘_ratio__length__plain_text_to_total_plain_text’] > 0.05)):
// empty elements
switch (true)
{
case (($D.parseOptions._elements_self_closing.indexOf(‘|’+_tag_name+’|’) > -1)):
case (($D.parseOptions._elements_ignore_tag.indexOf(‘|’+_tag_name+’|’) > -1)):
case (_tag_name == ‘td’):
break;
$D.getContent__find__getIsolatedTitleInHTML = function (_html)
{
// is it there?
if ($D.getContent__find__hasIsolatedTitleInHTML(_html)); else { return ”; }
// regex
var
_getTitleRegex = new RegExp($D.articleTitleMarker__start + ‘(.*?)’ + $D.articleTitleMarker__end, ‘i’),
_getTitleMatch = _html.match(_getTitleRegex)
;
// match?
if (_getTitleMatch); else { return ”; }
// return
return _getTitleMatch[1];
};
$D.getContent__find__isolateTitleInHTML = function (_html, _document_title)
{
// use document title
if ($D.$document.find(‘body’).attr($D.parseOptions._use_document_title_attribute) == $D.parseOptions._use_document_title_attribute_value)
{ return _html; }
// can’t just use (h1|h2|h3|etc)
// we want to try them in a certain order
// return?
switch (true)
{
case (!(_heading_length > 5)):
case (!(_heading_length < (65 * 3))):
case (!(_to_heading_length -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 -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 0 && (_offset + _needle.length) > _length) {
return false;
}
cnt++;
}
return cnt;
};
$D.getContent__find__isolateTitleInHTML__balanceDivsAtStart = function (_html)
{
// easy; remove all at begining
var
_h = _html.replace(/^(\s*]+>)+/gi, ”),
_r = /]+?)[^>]*>/gi,
_the_end_tag = ‘
if ((!(_start_tags > 0)) || (_start_tags 0)):
case (!(_firstCandidate._count__candidates > 0)):
case (!(_firstCandidate._count__pieces > 0)):
case (!(_firstCandidate._count__containers > 25)):
break;
default:
$D.debugTimerStart(‘ProcessSecond’);
var _processedCandidatesSecond = $D.getContent__processCandidates__second(_processedCandidates);
_secondCandidate = _processedCandidatesSecond[0];
$D.debugRemember(‘ProcessSecond’, $D.debugTimerEnd()+’ms’);
// they’re the same
if (_firstCandidate.__node == _secondCandidate.__node) { break; }
// debug
if ($D.debug)
{
// log second candidates
$D.log(‘First 5 Second Candidates:’);
for (var x in _processedCandidatesSecond)
{
if (x == 5) { break; }
$D.log(_processedCandidatesSecond[x], _processedCandidatesSecond[x].__node);
}
// highlight second
$D.debugOutline(_secondCandidate.__node, ‘target’, ‘second’);
}
// is what we found any good?
// ==========================
switch (true)
{
case ($D.getContent__find__hasIsolatedTitleInHTML(_aboveHTML)):
case (_differentTargets && (_aboveHTML.split(‘<a ').length < 3) && ($D.measureText__getTextLength(_aboveHTML.replace(/]+?>/gi, ”).replace(/\s+/gi, ‘ ‘)) ”); else
{
// if all else failed, get document title
// ======================================
// loop through pregs
// ==================
for (var i=0, _i=_doc_title_pregs.length; i 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 1 ? _doc_title_parts[0] : _documentTitle)
+ $D.articleTitleMarker__end
+ _foundHTML
;
if ($H.debug)
{
// writeLog
// ========
switch (true)
{
case (!(!($H.window.console && $H.window.console.log))): $H.writeLog = function (msg) { $H.window.console.log(msg); }; break;
case (!(!($H.window.opera && $H.window.opera.postError))): $H.writeLog = function (msg) { $H.window.opera.postError(msg); }; break;
default: $H.writeLog = function (msg) {}; break;
}
// log
// ===
$H.log = function ()
{
if ($H.debug); else { return; }
for (var i=0, il=arguments.length; i 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);
};
$H.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; }
if (range.commonAncestorContainer && range.commonAncestorContainer.ownerDocument); 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);
};
$H.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; }
if (range.commonAncestorContainer && range.commonAncestorContainer.ownerDocument); else { return null; }
var dummy = range.commonAncestorContainer.ownerDocument.createElement(“div”);
dummy.appendChild(range.cloneContents());
return dummy.textContent;
};
}
else {
arguments.calee = function (range) {
return null;
};
}
// recursive function
// ==================
var _recursive = function (_node)
{
// increment index — starts with 1
// ===============
_global__element_index++;
// start tag
// =========
if (_tag_is_ignored); else
{
/* mark */ _pos__start__before = _global__the_html.length;
/* add */ _global__the_html += ‘<'+_tag_name;
// attributes
// ==========
// allowed attributes
if (_tag_name in $H.parseOptions._elements_keep_attributes)
{
for (var i=0, _i=$H.parseOptions._elements_keep_attributes[_tag_name].length; i ”)
{ _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”‘; }
// add class name
// ==============
var _class_attribute = _node.getAttribute(‘class’);
if (_class_attribute > ”)
{ _global__the_html += ‘ class=”‘+_class_attribute+'”‘; }
// add highlight id — for EMs that are outside the global highlight
// ================
if (_tag_name == ’em’ && _modeToBuildHTMLIn != ‘everything’)
{
// with a fix for when an em is the first thing inside a parent element
switch (true)
{
case (_global__highlight_on):
case ((_rangeToBuildHTMLWith.startOffset == 0) && (_node.firstChild) && (_node.firstChild == _rangeToBuildHTMLWith.startContainer)):
break;
default:
var _highlight_id_attribute = _node.getAttribute($H.settings.highlightElementIdAttribute);
if (_highlight_id_attribute > ”)
{ _global__the_html += ‘ ‘+$H.settings.highlightElementIdAttribute+’=”‘+_highlight_id_attribute+'”‘; }
break;
}
}
// close start
// ===========
if ($H.parseOptions._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 ($H.parseOptions._elements_self_closing.indexOf(‘|’+_tag_name+’|’) > -1); else
{
for (var i=0, _i=_node.childNodes.length; i -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 += ”;
/* mark */ _pos__end__after = _global__the_html.length;
break;
}
// protected elements
// ==================
switch (true)
{
// some elemnts are protected from highlighting
case (($H.parseOptions._elements_highlight_protect.indexOf(‘|’+_tag_name+’|’) > -1)):
case ((_tag_name == ’em’) && $CJ(_node).hasClass($H.settings.highlightElementCSSClass)):
// so, if highlights are inside an already highlighted element –or an unhighlightable one– remove
// actually do it
_recursive(_elementToBuildHTMLFor);
// use em, instead of highlight
_global__the_html = _global__the_html
.replace(//gi, ‘‘)
.replace(//gi, ‘‘)
;
// return
return _global__the_html;
};
// build html for element with selected range }
// do range {
// ==========
$H.highlight__doRange = function (_range_to_highlight)
{
// get referrence elements
var
_commonAncestorElement = $H.highlight__getParentElementOfNode(_range_to_highlight.commonAncestorContainer),
_startElement = $H.highlight__getParentElementOfNodeWithThisParent(_range_to_highlight.startContainer, _commonAncestorElement),
_endElement = $H.highlight__getParentElementOfNodeWithThisParent(_range_to_highlight.endContainer, _commonAncestorElement)
;
// range not in container element
if (true
&& (_commonAncestorElement.tagName)
&& !($CJ.contains($H.settings.elementWhichMustContainAllHighlights, _commonAncestorElement))
) {
return false;
}
// arbitrary range exclusion
if ($H.callbacks.arbitraryRangeExclusion) {
if ($H.callbacks.arbitraryRangeExclusion(_range_to_highlight, _commonAncestorElement, _startElement, _endElement) === false) {
return false;
}
}
// selection id
var _selection_id = $H.rand(1, 1000);
while (true)
{
// nothing found
if ($H.$elementWhichMustContainAllHighlights.find(’em.’+$H.settings.highlightElementCSSClass+'[‘+$H.settings.highlightElementIdAttribute+’=”‘+_selection_id+'”]’).length > 0); else { break; }
// new id
_selection_id = $H.rand(1, 1000);
}
// chainging elements
// ==================
var _chaingingElements = [], _currElement = _startElement, _currChainging = false;
// resulting html might be something like “something something else”
// so we create a dummy span tag to eomcompass it, and then repalce the old text node with that
// create
var _newElement = $H.document.createElement(‘span’);
_newElement.innerHTML = _currBuiltHTML;
// result
_resNode = _newElement;
/* with (Evernote.evernotePopup) {
console.log(‘ ~~~ highlight.js gadit before |’ + docSelection + “|”);
console.log(‘ ~~~ from ‘ +docSelection.startOffset + ‘ to ‘ + docSelection.endOffset);
}*/
// first, last
$H.$elementWhichMustContainAllHighlights.find(’em.’+$H.settings.highlightElementCSSClass+’.’+$H.settings.highlightElementFirstCSSClass).removeClass($H.settings.highlightElementFirstCSSClass);
$H.$elementWhichMustContainAllHighlights.find(’em.’+$H.settings.highlightElementCSSClass+’.’+$H.settings.highlightElementLastCSSClass).removeClass($H.settings.highlightElementLastCSSClass);
// add buttons and classes
// =======================
var
_highlights_collection = $H.$elementWhichMustContainAllHighlights.find(’em.’+$H.settings.highlightElementCSSClass),
_highlights_collection_ids = [],
_curr_delete_button = false
;
// get all ids
_highlights_collection.each(function (_i, _e) {
_highlights_collection_ids.push($CJ(_e).attr($H.settings.highlightElementIdAttribute));
});
// highlight mouse enter
$H.$elementWhichMustContainAllHighlights.on('mouseenter', 'em.'+$H.settings.highlightElementCSSClass, function ()
{
var _highlight_id = $CJ(this).attr($H.settings.highlightElementIdAttribute);
// highlight delete click
$H.$elementWhichMustContainAllHighlights.on('click', 'em.'+$H.settings.highlightElementCSSClass+' a.'+$H.settings.highlightElementDeleteCSSClass, function ()
{
// get id
var _id = $CJ(this.parentNode).attr($H.settings.highlightElementIdAttribute);
// remove self
$CJ(this).remove();
// delete
$H.highlight__deleteHighlight(_id);
// callback
if ($H.callbacks.highlightDeleted) {
$H.callbacks.highlightDeleted();
}
});
};
// add mouse handlers }
// get clean html {
// ================
$H.getCleanHTML = function (_rawHTML)
{
// html
var _html = _rawHTML;
// remove all spans — spans hold deleted highlights, or useless helper elements
_html = _html.replace(/]*?)>/gi, ”);
_html = _html.replace(//gi, ”);
// highlight element
var _highlight_element_reg = new RegExp(‘]*?)’+$H.settings.highlightElementCSSClass+'([^>]*?)>([^>]+?)‘, ‘gi’);
_html = _html.replace(_highlight_element_reg, ‘$3’);
// double EMs
var _two_highlights_reg = new RegExp(‘([\\s\\S]*?)([ \\n\\r\\t]*?)([\\s\\S]*?)’, ‘gi’);
while (true && _html.match(_two_highlights_reg)) {
_html = _html.replace(_two_highlights_reg, ‘$1$3’);
}
// replace EMs
var _highlight_reg = new RegExp(‘([\\s\\S]*?)’, ‘gi’);
_html = _html.replace(_highlight_reg, $H.settings.highlightCleanHTMLElementStart+’$1’+$H.settings.highlightCleanHTMLElementEnd);
// write to frame
// ==============
var _doc = $N.$nextPages.find(‘#’+$N.settings.onCreateNextPageFramesUseThisIdPrefix+_pageNr).contents().get(0);
_doc.open();
_doc.write(_html);
_doc.close();
// add load handler
// ================
$N.$nextPages.find(‘#’+$N.settings.onCreateNextPageFramesUseThisIdPrefix+_pageNr).bind(‘load’, function ()
{
// done?
if ($N.$nextPages.find(‘#’+$N.settings.onCreateNextPageFramesUseThisIdPrefix+_pageNr).attr($N.settings.onLoadingNextPageFramesUseThisAttribute) == $N.settings.onLoadingNextPageFramesUseThisAttributeValue) { return; }
// can do?
var _doc = $N.$nextPages.find(‘#’+$N.settings.onCreateNextPageFramesUseThisIdPrefix+_pageNr).contents().get(0);
if (_doc); else { return; }
if (_doc.readyState == ‘interactive’ || _doc.readyState == ‘complete’); else { return; }
// mark
$N.$nextPages.find(‘#’+$N.settings.onCreateNextPageFramesUseThisIdPrefix+_pageNr).attr($N.settings.onLoadingNextPageFramesUseThisAttribute, $N.settings.onLoadingNextPageFramesUseThisAttributeValue);
// do
$N.nextPage__loadedInFrame(_pageNr, _doc.defaultView);
});
};
$N.nextPage__loadedInFrame = function (_pageNr, _pageWindow)
{
// find
// ====
var
_found = $D.getContent__findInPage(_pageWindow),
_foundHTML = _found._html,
_removeTitleRegex = new RegExp($D.articleTitleMarker__start + ‘(.*?)’ + $D.articleTitleMarker__end, ‘i’)
;
// get first fragment
// ==================
var _firstFragment = $D.nextPage__getFirstFragment(_foundHTML);
// gets first 2000 characters
// diff set at 100 — 0.05
switch (true)
{
case ($D.levenshteinDistance(_firstFragment, $N.nextPage__firstFragment__firstPage) < 100):
case ($D.levenshteinDistance(_firstFragment, $N.nextPage__firstFragment__lastPage) ” ? $D.document.title : ”));
_foundHTML = _foundHTML.replace(_removeTitleRegex, ”);
// once with article title
_foundHTML = $D.getContent__find__isolateTitleInHTML(_foundHTML, $D.articleTitle);
_foundHTML = _foundHTML.replace(_removeTitleRegex, ”);
// sort — the less points, the closer to position 0
// ====
_links.sort(function (a, b)
{
switch (true)
{
case (a._distance b._distance): return 1;
default: return 0;
}
});
// return
return _links;
};
// find }
// start {
// =======
$N.start = function ()
{
// first fragments
$N.nextPage__firstFragment__firstPage = $D.nextPage__firstFragment__firstPage;
$N.nextPage__firstFragment__lastPage = $D.nextPage__firstFragment__lastPage;
// first page
$N.pages = [{ ‘_url’: $D.window.location.href }];
// _resetBase
switch (true)
{
case (!(‘base’ in $R.appliedOptions)):
case (!(_encodedOptions[‘base’] == $R.appliedOptions[‘base’])):
_resetBase = true;
break;
}
// _resetOptions
for (var _option in _possible_options)
{
switch (true)
{
case (!(_option in $R.appliedOptions)):
case (!(_encodedOptions[_option] == $R.appliedOptions[_option])):
_resetOptions = true;
break;
}
// stop
if (_resetOptions) { break; }
}
// appliedOptions and optionsToApply
for (var _option in _possible_options)
{
$R.appliedOptions[_option] = _encodedOptions[_option];
_decodedOptions[_option] = $R.decode(_encodedOptions[_option]);
}
// apply stuff
// ===========
// base
if (_resetBase)
{
// remove old
$R.$iframeDocument.find(‘#baseCSS’).remove();
// add new
if (_decodedOptions[‘base’] > ”)
{
$R.$iframeDocument.find(‘head’).append(”
+ ‘ ‘
);
}
}
// options
if (_resetOptions)
{
var _cssText = $R.getCSSFromOptions(_decodedOptions);
// remove old
// ==========
$R.$iframeDocument.find(‘#optionsCSS’).remove();
// new
// ===
var _cssElement = document.createElement(‘style’);
_cssElement.setAttribute(‘type’, ‘text/css’);
_cssElement.setAttribute(‘id’, ‘optionsCSS’);
if ( sel && !hasSelection && deep ) {
var nestedDocs = Evernote.Utils.getNestedDocuments( doc );
for ( var i = 0; i 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 && false; // disabled, because no need to search selections in this elements.
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 );
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
}
};
// ]]>// <![CDATA[
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();
var serializer = new Evernote.NodeSerializer( window, new Evernote.ClipFullStylingStrategy(), null, true );
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);
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();
var wait = doc.getElementById( Evernote.ClipNotificator.WAIT_CONTAINER_ID );
if ( wait ) {
wait.style.opacity = “0”;
if (immediately) {
wait.parentNode.removeChild( wait );
} else {
setTimeout( function() {
if ( wait.parentNode ) {
wait.parentNode.removeChild( wait );
}
}, 300 );
}
}
};
// ]]>// <![CDATA[
/**
* Represents clipper object that is capable of clipping elements from pages or clip elements based on preferences.
*/
Evernote.Clipper = {
var veil = document.createElement("div");
veil.id = "evernoteContentVeil";
var inner = document.createElement("div");
inner.id = "evernoteInnerBox";
var pageCounter = document.createElement("div");
pageCounter.id = "evernotePageCounter";
veil.appendChild(pageCounter);
veil.appendChild(inner);
var pageHeight = document.body.scrollHeight; // used for infinite scroll handling
/*
IE10 doesn't support pointer-events:none;
So we had to replace existing veil with new one, combined of 8 divs.
Four of them has border to outline content, and four divs in corners has white filling only.
There is no any element in center, over the content, so nothing will catch mouse events.
It helps other functions, especially html highlighter, works as expected.
var veilTop = document.createElement("div");
veilTop.id = "evernoteContentVeilTop";
var veilLeft = document.createElement("div");
veilLeft.id = "evernoteContentVeilLeft";
var veilRight = document.createElement("div");
veilRight.id = "evernoteContentVeilRight";
var veilBottom = document.createElement("div");
veilBottom.id = "evernoteContentVeilBottom";
var veilNW = document.createElement("div");
veilNW.id = "evernoteContentVeilNW";
var veilNE = document.createElement("div");
veilNE.id = "evernoteContentVeilNE";
var veilSE = document.createElement("div");
veilSE.id = "evernoteContentVeilSE";
var veilSW = document.createElement("div");
veilSW.id = "evernoteContentVeilSW";
var veilAll = Evernote.JQuery([veilTop,veilBottom,veilLeft,veilRight]);
var veilCorners = Evernote.JQuery([veilNW,veilNE,veilSE,veilSW]);
veilAll.addClass('EvConVeil');
veilCorners.addClass('EvConVeilCorn');
function fireClickUnderVeil(evt) {
var veil = Evernote.JQuery(this);
veil.hide();
var bottomElement = document.elementFromPoint(evt.clientX, evt.clientY);
veil.show();
bottomElement.click();
}
// make veil imperceptible for mouse clicks.
veilAll.click(fireClickUnderVeil);
veilCorners.click(fireClickUnderVeil);
var tooltipTimeout;
var topExpandContract;
var bottomExpandContract;
for (var i = 0; i < 2; i++) {
var expand = document.createElement("div");
var contract = document.createElement("div");
expand.className = "evernoteArticleExpand";
contract.className = "evernoteArticleContract";
function nudgeMouseoutHandler() {
clearTimeout(tooltipTimeout);
this.className = this.className.replace(/\s*tooltipon/g, "");
}
// 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 currentlyShownElt = null;
var currentRectOffsetTop = 0;
var currentRectOffsetLeft = 0;
var currentlyStatic = false;
var currentlyShadowBox = false;
function hide() {
if (Evernote.ElementExtension.hasParentNode(veil)) {
veilAll.each(function(){this.parentNode.removeChild(this)});
veilCorners.each(function(){this.parentNode.removeChild(this)});
veil.parentNode.removeChild(veil);
}
}
function isHidden() {
if (Evernote.ElementExtension.hasParentNode(veil)) {
return false;
}
return true;
}
// 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 getPageHeight() {
var h = Math.abs(window.innerHeight – document.body.scrollHeight) 15) return wh;
return h;
}
function revealRect(rect, elt, staticView, shadowBox) {
// 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 = veil.style.width.replace(“px”, “”);
var veilHeight = veil.style.height.replace(“px”, “”);
function revealStaticRect(rect, elt, shadowBox) {
revealRect(rect, elt, true, shadowBox);
}
function outlineElement(element, scrollTo, shadowBox, articleAdjustment) {
// See notes in Preview.js for why we use this method instead of just calling element.getBoundingClientRect().
var rect = Evernote.contentPreviewer.computeDescendantBoundingBox(element);
if (rect) {
reset(articleAdjustment);
revealRect(rect, element, true, shadowBox);
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";
}
showElements(tagName, exceptInElement);
}
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;
}
}
}
}
function getElement() {
return veil;
}
function setPageCount(count) {
if (!count) {
pageCounter.innerText = "";
} else if (count == 1) {
//TODO: test l10n
pageCounter.innerText = "oneMorePageFound";
} else {
//TODO:test l10n
pageCounter.innerText = "morePagesFound" + count;
}
pageCounter.scrollIntoView(true);
}
var onScrollHandle = function(e) {
if (currentlyShownRect && !currentlyStatic) {
var rect = {
top: currentlyShownRect.top,
bottom: currentlyShownRect.bottom,
left: currentlyShownRect.left,
right: currentlyShownRect.right,
width: currentlyShownRect.width,
height: currentlyShownRect.height
};
var vert = Evernote.Utils.scrollTop() – currentRectOffsetTop;
var horiz = Evernote.Utils.scrollLeft() – currentRectOffsetLeft;
function sendMessageToPopup( msg ){
// send message to global tools
var zoomModifier = screen.deviceXDPI / screen.logicalXDPI;
with (borderDiv.style) {
var topX = pixelLeft * zoomModifier;
var topY = pixelTop * zoomModifier;
var bottomX = (area.width() – pixelRight) * zoomModifier;
var bottomY = (area.height() – pixelBottom) * zoomModifier;
}
// If any side of the rectangle that user is drawing is smaller than 16px then we interpret it as a
// single click and should make a fullscreen capture.
// 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 documentMode = document.documentMode;
var url = document.location.href;
// Very slow and useless assignment, takes more than a second. Temporary commented for speed up [actimind]
// 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 cleanArticles = [];
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 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 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 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)
{
Evernote.Logger.warn(“Couldn’t find clearly!”);
clearlyCallback(null, callback);
}
else {
Evernote.Logger.debug(“Call clearly to select article”);
try {
Evernote.ClearlyController.getContentElementAndHTML(function(data){clearlyCallback(data, callback)});
} catch(e) {
Evernote.Logger.error(“Failed to find article by clearly due to error ” + e.message);
clearlyCallback(null, callback);
}
}
}
// If the page is big enough, clearly is excruciatingly slow. We’ll just get the whole page.
// TODO: Clearly was updated. Check, if big pages are still problem
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 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;
}
function getBiggestImage(callback) {
getDefaultArticle(function(art) {
var imgs;
if (art) {
imgs = art.querySelectorAll(“img”);
} else {
imgs = document.querySelectorAll(“img”);
}
var maxHeight = 0;
var maxWidth = 0;
var maxImage;
for (var i = 0; i maxWidth * maxHeight) {
maxHeight = h;
maxWidth = w;
maxImage = imgs.item(i).src;
}
}
callback({ src: maxImage, width: maxWidth, height: maxHeight });
});
}
// 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 getUrl() {
return url;
}
function getText(node, soFar, maxLen) {
if (node.nodeType == Evernote.Node.TEXT_NODE) {
var trimmed = (node.textContent) ? Evernote.JQuery.trim(node.textContent).replace(/\s+/g, " ") : "";
if (trimmed === " " || trimmed === "") return soFar;
return soFar + " " + trimmed;
}
var banned = [
"style",
"script",
"noscript"
];
if (node.nodeType == Evernote.Node.ELEMENT_NODE) {
if (Evernote.ArrayExtension.indexOf(banned, node.nodeName.toLowerCase()) == -1) {
for (var i = 0; i 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 // <![CDATA[
Evernote.Scroller = function Scroller( tab ) {
this.initialize( tab );
};
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 // <![CDATA[
function ContentPreview() {
Evernote.Logger.debug("Start creating preview box");
var contentVeil = new ContentVeil();
var screenshotVeil = new ScreenshotVeil();
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;
var snippet = null;
function buildUrlElement() {
var urlEl = document.createElement("div");
urlEl.id = "evernotePreviewContainer";
var className = "yui3-cssreset";
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.documentElement.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 (isNaN(w) || isNaN(h)) {
// IE8
w = Evernote.JQuery(urlElement).width();
h = Evernote.JQuery(urlElement).height();
}
if (w && h) {
urlElement.style.marginLeft = (0 – w / 2) + "px";
urlElement.style.marginTop = (0 – h / 2) + "px";
}
function buildContent ( data ) {
var title = PageContext.title;
var url = PageContext.url;
var favIconUrl = PageContext.getFavIconUrl();
snippet = data.replace(/(]+)>)/ig,””); // remove html tags from text
Evernote.ClearlyController.getClearlyArticleText( function (data) {
buildContent(data._html);
});
}
// 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();
screenshotVeil.hide();
hideUrlElement();
}
function _previewArticle () {
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), selectionFrame, true);
Evernote.Logger.debug(“contentVeil.show “);
contentVeil.show();
}
else {
// TODO: Scroll into article view.
contentVeil.outlineElement(previewElement, false, true);
window.scrollTo(0, previewElement.offsetTop – 30);
}
}
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) {
// 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;
}
// 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;
} else {
previewElement = descendTreeUntilUniqueElement(previewElement);
}
break;
Evernote.Logger.debug(“nudgePreview: previewElement.children.length = ” + previewElement.children.length);
for (var i = 0; i 30 && h > 15)
}
// if (enoughSize(previewElement) === false) return;
// 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 = range.getBoundingClientRect();
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;
}
// If every edge of the rectangle is in negative space,
function rectIsOnScreen(rect) {
// rtl pages have actual content in "negative" space. This case could be handled better.
if (document.dir == "rtl") {
return false;
}
// If both top and bottom are in negative space, we can't see this.
if (rect.bottom < 0 && rect.top < 0) {
return false;
}
// Or, if both left and right are in negative space, we can't see this.
if (rect.left < 0 && rect.right 1) {
newRect = unionRectangles(tempRect, 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};
var rect = element.getBoundingClientRect();
var li = rect.top + window.pageYOffset
return applyElementRect(element, {
bottom: rect.bottom + window.pageYOffset,
height: rect.height,
left: rect.left + window.pageXOffset,
right: rect.right + window.pageXOffset,
top: rect.top + window.pageYOffset,
width: rect.width
});
}
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 // // <![CDATA[
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;
},
containsCaseIgnore : function(element, searchStr) {
if(!element) {
return false;
}
for(var i = 0; i >> 0;
if (typeof fun != “function”)
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i // <![CDATA[
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 // <![CDATA[
Evernote.GlobalUtils = {};
(function(){
var urlMatcher = /^(.*?):\/\/((www\.)?(.*?))(:\d+)?(\/.*?)(\?.*)?$/;
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"]) {
// TODO: replace "oldlipper" with universal path
Evernote.Utils.changeBackgroundImage(element, Evernote.Addin.getPath("resources") + 'oldclipper/' + 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) {
var node = element.nodeName.toLowerCase();
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":
case "radio":
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;
} else {
element.innerHTML = 'l10n error'; // to spot if something goes wrong
}
}
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;
};
/**
* 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 length) {
return (str.substring(0, length-3) + addition);
}
return str;
},
/**
* Change new line symbol to html
*/
newLineToBr : function(str) {
return str.replace(/(\r\n|\n|\r)/gm, ”
“);
},
/**
* 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 = 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);
}
}
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
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 😛
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);
if (!nodeInfo2.node) {
nodeInfo2.node = parentElement2;
}
//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;
},
var elem = Evernote.JQuery('#' + Constants.POST_CLIP_DIALOG_ID);
var clipboard_container = elem.find('#' + 'evn-clipboardCopy-container');
var titleField = elem.find('.noteTitle');
var link = Evernote.pageInfo.getUrl();
var shareTitle = 'error';
// subscribe to response from addin
Evernote.ResponseReceiver.subscribe(this);
var _title = '';
var _notebook = '';
var clipping_message = Evernote.Addin.getLocalizedMessage(Evernote.Messages.CLIPPING);
var clipped_message = Evernote.Addin.getLocalizedMessage(Evernote.Messages.CLIPPED);
var message = elem.find('.clippedMessage');
var closeButton = elem.find('.closeCross');
var openButton = elem.find('#openButton');
var shareButton = elem.find('#shareButton');
var shareIcons = elem.find('.shareButton');
var cbInput = elem.find('.evn-pcp-clipboard-input');
var cbMessage = elem.find('.evn-pcp-clipboard-message');
var cbButton = elem.find('.evn-pcp-clipboard-button');
var errorLink = elem.find('#evn-show-logs');
var errorMsg = elem.find('.evn-error-desc');
function showLogs() {
var logFile = Evernote.Addin.getPath("logfile");
Evernote.Addin.openLocalFile(logFile, BrowserNavConstants.NAVOPENNEWTAB);
}
function modifyToCurrentIE() {
if (document.documentMode == '9') {
elem.addClass('evn-iexplorer9');
} else if (document.documentMode == '7' || Evernote.BrowserDetection.isIE7()) {
elem.addClass('evn-iexplorer7');
}
}
function localize() {
Evernote.GlobalUtils.localize(elem.get(0));
}
function copyToClipboard(){
var clipSucceed = window.clipboardData.setData('Text', link);
var isAllowed = window.clipboardData.getData('Text');
if (isAllowed == "") { // Could be empty, or failed
// Verify failure
if (!window.clipboardData.setData('Text', 'test_string'))
isAllowed = null;
}
Evernote.ClipRules.SELF_CLOSING_NODES = {
“IMG” : null,
//”INPUT” : null,
“BR” : null
};
// ]]>// <![CDATA[
/**
* 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.CSS_GROUP.getExtForStyle = function ( name ) {
var list = this[ name ];
var extList = [ ];
if ( list ) {
for ( var i = 0; i = 0 ) {
var tmp = list[ i ];
extList.push( tmp.replace( “+”, “” ) );
}
else {
extList.push( name + “-” + list[ i ] );
}
}
return extList;
}
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 ( 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.
Evernote.ClipStyle.prototype.toString = function () {
var str = "";
var stylesNames = this.getStylesNames();
for ( var i = 0; i 0 ) {
str += styleName + “:” + value + “;”;
}
}
/**
* 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;
}
return "“;
}
catch ( e ) {
Evernote.Logger.error( “VideoElementSerializer.serialize() failed: error = ” + e );
}
return “”;
};
// ]]>// <![CDATA[
/**
* 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:
*
*
* - 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)
*
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;
}
}
}
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 this.constructor.DEFAULT_THUMB_WIDTH / this.constructor.DEFAULT_THUMB_HEIGHT ) {
imgAttrStr += “height=\”” + h + “\””;
}
else { // scale by width
imgAttrStr += “width=\”” + w + “\””;
}
}
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 // // <![CDATA[
Evernote.NotebooksLoader = {
notebooks: [],
// TODO: add cache;
getNotebookByUid: function(uid) {
Evernote.ResponseReceiver.subscribe(this);
Evernote.Addin.getNotebooks(document);
for(var i = 0; i // // // // // //