Really Useful Javascript

by Dale Stubbart

version 1.1

x_press code explained

Portions of x_press.js code are explained here. To see all the code go to x_press.js.

x_d_w(), x_getPropertyValue()

x_d_w() consists of one line of code function x_d_w(x_a) {document.write(x_a)}. x_d_w() provides a shortcut for writing document.write. If you have several contiguous x_d_w() statements, combine them into one, or build a string and just write out that string once. This will speed up your javascript.
x_pad() left pads a string with zeros
function x_pad(x_string_in,x_string_in_length){
return '000000000000000000'.substring(0,x_string_in_length-x_string_in.length)+x_string_in;}
This works even if x_string_in_length-x_string_in.length=zero, because that results in a null string.
x_getPropertyValue() is in x_press_in_body.js rather than in x_press.js. This is because this piece of code has to reside in the <body> rather than the <head> of your html. I get a lot of help for writing javascript from W3Schools which tell me syntax and give examples to try. CSS-Tricks is also usually helpful. This piece of code I put together with help from Ruzee. The code is
function x_getPropertyValue(x_gpv_property){
var x_gpv_cs=document.defaultView.getComputedStyle(document.body,null);
return x_gpv_cs.getPropertyValue(x_gpv_property);}
Set a variable to hold the computed styles of the document.body. Then return the specific property value via the builtin-method getPropertyValue. document.body or any element can be passed to getComputedStyle. If the style is set on an element, it is available via other means. But if it is not set, it is only available as a computed style, and this way must be used. getComputedStyle works whether the style is set or computed.
function x_is_stylesheet_used(x_stylesheet_filename_in){
if(window.x_press_stylesheet_is_used === undefined){x_press_stylesheet_is_used=false;}
use window. because x_press_stylesheet_is_used is a global var rather than local var. Check x_press_stylesheet_is_used is checked so don&';t have to loop process link elements multiple times if x_is_style_sheet_used() is called from multiple places or multiple times.
var x_links=document.getElementsByTagName('link'); get all link tags since they contain stylesheets
for (i = 0;i < x_links_limit;i++) {x_ss_found=x_links[i].getAttribute('href');} get filename (url) of stylesheet (ss)


x_press() expands shorthand entities and spans. In x_press_init()
Set up global variables (no var) which can be set by in javascript in the html to override or add to the functionality of x_press().
In x_press()
var i;var j;var k;var s;var iH=document.body.innerHTML;
var x_press_punctuation_fr=["'","l'","r'",'l"','r"','m-','n-','...','?v','!v'];
var x_press_punctuation_to=["rsquo"/*apostrophe*/,"lsquo","rsquo",'ldquo','rdquo','mdash','ndash','hellip','iquest','iexcl'];

Set up local variables including iH which holds the inner HTML of the document.body. Text in iH will be changed from the shorthand notation to what is actually needed. Set up the from and to arrays. Each item in the arrays will be preceded by & and ended by ;, so those don&';t need to be included. Several other arrays are set.
var x_press_fr=[];var x_press_to=[];
for (i = 0; i < x_press_extra_fr.length; i++){

Load the actual from/to arrays, starting with the extra arrays, so that those will be processed first, overriding anything set in other arrays (because those shorthand codes will already be expanded). replace&...;g replaces all occurrences (g for global). Replace < with &lt; and > with &gt; in the from because the browser has already changed them. push each item onto the end of the array. Do the same for the spans, except don&;'t replace < and >.
for (i = 0; i < x_press_fr.length; i++){
x_p_f = '&amp;'+x_press_fr[i]+';';x_p_t = '&'+x_press_to[_i]+';';
pos = iH.indexOf(x_p_f);while (pos > 0){iH=iH.replace(x_p_f,x_p_t);pos = iH.indexOf(x_p_f);}}

Surround each item of the array with & and ;. Loop through replacing each occurrence of the item in the body innerHTML. Update the body innerHTML. The loop could possibly be written with a regular expression, using the g option. This code does the same thing, was much easier to write, and I didn&';t have to worry about the regular expression misinterpreting the x_press entities.


x_emoji_init() sets the following global variables.
x_emoji_color_names=['base', 'face', 'hand', 'heart', 'monkey','monk', 'cat', 'person','weather','red', 'purple','blue', 'yellow','pink', 'green', 'gray', 'black','brown','orange','white'];
x_emoji_color_codes=['191970', 'D2B48C', 'DEB887', 'CD5C5C', 'D2691E', '191970', 'FF8C00', '191970', '191970', 'ff0000', 800080', '0000ff', 'ffff00', 'FAAFBE', '00ff00', '808080', '000000', 'A52A2A', 'ffa500', 'C0C0C0'];

Using global variables so they can be modified outside the function. Set up two arrays, one with color generic names and one with corresponding color codes. Set limit to -1 to be interpreted as total length later.

x_emoji() turns emoji codes in to unicode characters representing the emoji codes. This will result differently than a smart phone, but will still give you a good representation.
for (i = 0; i < x_emoji_code_extra.length; i++){
x_emoji_code.push('joy', 'heart_eyes', 'unamused', 'blush', 'two_hearts', 'weary', 'ok_hand', 'pensive', 'smirk', 'grin');
x_emoji_unicode.push('1f602', '1f60d', '1f612', '1f60a', '1f495', '1f629', '1f44c', '1f614', '1f60f', '1f601');
x_emoji_color.push('face', 'face', 'face', 'face', 'heart', 'face', 'hand', 'face', 'face', 'face');

Load the extra (possibly overridden in html) array first so it is handled before anything else, thus overriding when duplicate. Three arrays - x_emoji_code, x_emoji_unicode, and x_emoji_color are then loaded with the 250 most popular emoji codes on twitter which have a unicode representation (first 10 are shown here). When x_emoji() encounters a value in x_emoji_code which is preceded and followed by :, it replaces it with a <span> which includes the corresponding value in x_emoji_unicode which is styled with color in corresponding value of x_emoji_color. Then if x_emoji_limit = -1 (not changed in html), it is set to the length of the array.
Next, replace the values
for (i = 0;i < x_emoji_limit; i++){
x_emoji_f = ':'+x_emoji_code[i]+':';
pos = iH.indexOf(x_emoji_f);
if emoji for following color is same as emoji for this color, it is already set. Do not look it up again. This really sped up this function.
while (pos > 0){
for (j = 0;j < x_emoji_color_names_limit; j++){
if (x_emoji_color_names[j] == x_emoji_color[i]){x_emoji_this_color_code = x_emoji_color_codes[j]; j=x_emoji_color_names_limit;}
} x_emoji_color_set=true;
} x_emoji_t = '<pan style="';
x_emoji_t+= 'color:#'+x_emoji_this_color_code+';'+x_emoji_style+'">';
x_emoji_t+= '&#x'+x_emoji_unicode[i]+';';
x_emoji_t+= '</span>';
pos = iH.indexOf(x_emoji_f);}}
x_emoji_f = '\:\\';x_emoji_t = ':';
handle back slash following : to not interpret as emoji code.
pos = iH.indexOf(x_emoji_f);while (pos > 0){iH=iH.replace(x_emoji_f,x_emoji_t);pos = iH.indexOf(x_emoji_f);}


x_accent() combines a letter with a following accent mark, using three arrays. Letter/Accent combination must be preceded by & and followed by ;.
var x_accent_fr=["'", "`", ",", "^" , "..", "_", "~", "o", "c", "u", "v", ".", "-", '"'];
var x_accent_letter_fr=[];for(i = 0; i < 26; i++){k=i+65; x_accent_letter_fr[i*2] = String.fromCharCode(k); x_accent_letter_fr[i*2+1] = x_accent_letter_fr[i*2].toLowerCase();}
load this array with each letter of the alphabet, first in uppercase then in lower case.
var x_accent_to=["acute", "grave", "cedil", "circ", "uml", "macr", "tilde", "ring", "ogon", "breve", "caron", "dot", "strok", "dblac"] these are the html entities for accent marks. html entities like &Aacute; combine a letter with the accent mark.
If testing, loop through unicode characters 192 to 383 (decimal), skipping those which aren&';t accented characters and those which have no html entity.
for (i = 0; i < x_accent_fr.length; i++){
for (j = 0; j < x_accent_letter_fr.length; j++){
x_a_f = '&'+x_accent_letter_fr[j]+x_accent_fr[i]+';';x_a_t = '&'+x_accent_letter_fr[j]+x_accent_to[i]+';';
pos = iH.indexOf(x_a_f);while (pos > 0){iH=iH.replace(x_a_f,x_a_t);pos = iH.indexOf(x_a_f);}}}


x_script(string,style) writes out the string using the style. This is done by way of html entities. &Ascr; writes A in a handwriting script (scr). &Aopf; is outlined. &Afr is old english.
if(x_s_style==null){x_s_style='handwriting'}; default to handwriting script.
x_s_style=x_s_style.toLowerCase(); change style passed to lowercase.
x_s_style=x_s_style.replace('-','');x_s_style=x_s_style.replace(' ',''); remove hyphens and spaces in the style.
&...; if (x_in.match(/[a-z]/i)){&...; only process letters. i means ignore case.


x_soc() takes the most to implement of these functions. First call x_soc_init() in the <head> of your html. This sets various global variables which you can override in your html. Then x_press_in_body.js must be placed in the <body> of your html. This provides function x_getPropertyValue() which was discussed at the top of the page. Then, where you want the social media buttons to display, call x_soc_init_2() override anything that set if you wish. Then call x_soc(). In x_soc_init()
x_soc_piisvideo='false'; // Pinterest IsVideo 'true'/'false' set to the literal 'true' or 'false' not to the boolean true or false.
In x_soc_init_2()
if(x_soc_base_color==''){if(typeof(x_getPropertyValue) == "function"){x_soc_base_color=x_getPropertyValue('color');}} This sets x_soc_base_color to the color of document.body if you haven&';t set it and if you&';ve included x_press_in_body.js (it&';s a function).
The following four arrays are initialized. x_soc_site contains the social media two-character abbreviations used by x_soc(). x_soc_title contains the title you want to highlight when someone hovers over the button. x_soc_link_text contains the link text including any styles for individual characters. x_soc_style contains the style for each button.
x_soc_site=['fb','tw','li','gp','tu','em','pr']; The complete list of codes is bu buffer; dg digg; dl delicious; em email; en evernote; fb facebook; ff friendfeed; gb googlebookmarks; gp google+; li linkedin; nv newsvine; pf; pi pinterest; pr print; ps posterous; rd reddit; sd slashdot; su stumbleupon; tn technorati; tu tumblr; tw twitter
x_soc_link_text=['&fopf;<span style="font-size:smaller"><sub>&#x1F4D6;</sub></span>','&tamp;opf;<span style="font-size:smaller"><sub>&#x1F426;</sub></span>','<span style="font-size:smaller">&#x1F517;</span>&iamp;opf;&nopf;','&gamp;opf;&#x2719;','𝕥<span style="font-size:smaller"><sub>&#x1f37b;</sub></span>','&eamp;opf;<span style="font-size:smaller"><sub>&#x1F4E9;</sub></span>','&pamp;opf;<span style="font-size:smaller"><sub>&#x1F4DC;</sub></span>'];<br> x_soc_style=['color:#3B5998','color:#55ACEE;','color:#057BAD;font-family:Arial Black,arial,helvetica,verdana,tahoma,sans-serif;','color:#4285F4;','color:#475467;padding-top:16px;min-height:46px;','color:'+x_soc_base_color,'color:'+x_soc_base_color];

x_soc() puts it all together. First get all the open graph and twitter meta tags and store them in variables. This meta tags are og:title, og:url, og:image, og:description, og:site_name, twitter:card, twitter:site, twitter:title, twitter:description, twitter:image. Hopefully, you included those in your lt;head>.
for (i = 0;i < x_soc_metas_limit;i++) {
if (x_soc_metas[i].getAttribute('property') == 'og:title') {og_title = encodeURIComponent(x_soc_metas[i].getAttribute('content'));}

Set up each sharing link
twshare=''+tw_title+'&url='+og_url+'&via='+tw_site.substring(3);if(twhashtags=''){}else {twshare+='&hashtags='+twhashtags;}
substring(3) starts at offset position 3 and goes to the end. twitter:site='@ybecojourney' sets the tag to my twitter site. Javascript reads this as %40ybecojourney. So, substring(3) skips the first 3 and results in ybecojourney. Javascript offset positions start with 0.
x_soc_emshare='mailto:?subject='+tw_title+'&body='+x_soc_embodylabel+' '+og_url+'%0D%0A'+og_desc;
%0D%0A is a carriage return line feed in Javascript.
x_soc_prshare='javascript:';if(x_soc_pralert=''){}else {x_soc_prshare+='alert('+x_soc_pralert+');';};x_soc_prshare+='window.print()"';
The following code handles setting only the first and last border-radius if that&';s what you specified in x_soc_border_radius_first_last (not 0px).
if (x_soc_border_radius_first_last=='0px'){} else {s+='border-top-left-radius:'+x_soc_border_radius_first_last+';border-bottom-left-radius:'+x_soc_border_radius_first_last+';'}
var site_limit=x_soc_site.length;
var site_limit_minus_1=site_limit - 1;
for (i = 0;i < site_limit_minus_1; i++){s+=x_soc_site_button(i);}
if (x_soc_border_radius_first_last=='0px'){} else {x_soc_button_style+='border-top-right-radius:'+x_soc_border_radius_first_last+';border-bottom-right-radius:'+x_soc_border_radius_first_last+';'}

The above code calls x_soc_site_button(index)
function x_soc_site_button(i){
if (x_soc_site[i] == 'em' || x_soc_site[i] == 'pr'){
email and print are structured differently from the others
return '<div style="'+x_soc_button_style+x_soc_style[i]+'" title="'+x_soc_title[i]+'"><a href="'+eval('x_soc_'+x_soc_site[i]+'share')+'" style="'+x_soc_a_style+'">'+x_soc_link_text[i]+'</a></div>';}

return '<div style="'+x_soc_button_style+x_soc_style[i]+'"><a href="'+eval('x_soc_'+x_soc_site[i]+'share')+'" target="_blank" title="'+x_soc_title[i]+'" style="'+x_soc_a_style+'">'+x_soc_link_text[i]+'</a></div>';}}


x_date calls x_date_fmt and writes the result.
function x_date(x_date_in, x_date_fmt_out){
Note: If x_date_in is string, separate date parts with slash to pass the date regardless of timezone. Separate date parts with hyphen to pass the date using time zone

x_date_fmt formats the date. You can call this directly if you only want to format the date and not output the results immediately.
var x_date_dd_name = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
var x_date_mm_name = ["January","February","March","April","May","June","July","August","September","October","November","December"];
if(typeof x_date_in === 'string'){x_date_in=new Date(x_date_in)}
if x_date_in is a string, make it a date.
var x_date_yyyy=x_date_in.getFullYear(); start getting date parts
var x_date_mm=x_date_in.getMonth()+1; month is 0:11, so make it 1:12
var x_date_hh24=x_date_in.getHours();
handle am/pm
Next, start replacing format codes, starting with the longest versions of the strings (yyyy before yy), so that if yy is 16, yyyy doesn&';t end up being 1616.
var x_date_out=x_date_fmt_out;preferred to use different variable in case I still needed to refer to the original one.
x_date_out=x_date_out.replace('yyyy',x_date_yyyy.toString()); change integers to strings.
x_date_out=x_date_out.replace('yy',x_pad(x_date_yyyy.toString().substr(2,2),2)); x_pad is called which left pads with zero. x_pad is discussed in detail at the top of the page.
if seconds are zero, suppress them and the preceding : or . if using ss for seconds format code. Do not suppress if using sc for seconds format code.
var x_date_ss_padded=x_pad(x_date_ss,2).toString();
if(x_date_ss==0){x_date_out=x_date_out.replace(':ss','');x_date_out.replace('.ss','')} else{x_date_out=x_date_out.replace('ss',x_date_ss_padded);};