February, 2018: 29 posts.
from Instagram https://www.instagram.com/p/Bev7I9eFiHG/
via IFTTT
THIS IS THAT
from Instagram https://www.instagram.com/p/Be3X6cPF-NL/
via IFTTT
NORTH PARK
Random Notes on #lightningnow Tour / Trailhead / Salesforce
On January 29th and 30th I attended the Lighting Tour of Salesforce.com that was held here in San Diego. I had a lot of fun, and got a great sense that my skills in web development may have a great deal of carryover into working with and developing for Salesforce.
Cutest stickers at @salesforce #lightningnow seminar here in San Diego. Added to my iPad though I took my notes on paper today. Day 2 of #lightningnow learning about Kanban view inside @Salesforce + bonus t-shirt! Remain impressed by quality of Trailhead exercises for a novice like me. I also like that it’s kind of Shazam!/Mage/Captain Marvel.

In web development one has to be cognizant of issues related to caching when making frequent updates. Here’s the setting you’d look for to make sure you’re seeing freshly edited content.

I was very impressed with the API versioning that’s a part of Salesforce. You can target different versions of Apex and in this way you can migrate to newer API versions as you need to in a manner that’s safe. Salesforce can keep innovating, and your apps won’t break. That’s smart.
I was also very interested to see the differences in code from “old style” and their “new style.” Of course I had no concept of the older style but I can see that they’ve taken some time to encapsulate very robust and common functionality in ways that are quicker to develop for.
from Instagram https://www.instagram.com/p/Be_X4LnldAg/
via IFTTT
Me & Crystal. 1982?
Backup your Soundcloud files to Archive.org
Well here’s something cool! My pal Dennis Wilen backed up his Soundcloud hosted files to Archive.org – We backed up my SoundCloud to Archive.org and you can too.
There’s a shell script by Tom Higgins that facilitates it.
I don’t understand the excess rules about ferrets or the deficit of rules about guns.
We (the government) regulate hairdressers and car exhaust and doctors and lawyers and how you add a new room to your house and we license you to drive a car and regulate boats and regulate your speed on the interstate and how you educate your children and test whether your toys are safe and whether your lettuce is clean and we regulate what the word “organic” means on a food package and we regulate how people houses are sold so it’s fair and we monitor air quality and we regulate how much you get paid on unemployment and we regulate how and who can vote and we have rules on lead in paint and we regulate if you can own a ferret in some places. Most of us see these as good things because a hairdresser not meeting standards can hurt you and cars with too much emissions cause smoke and untrained doctors and lawyers are a terrible idea and you need to learn to drive a car properly if you’re going to drive and if you’re going to teach your kids yourself you aught to do it right and if the lettuce isn’t clean you can get really sick and if something is “organic” it should actually mean something and the real estate business has a really shady history of treating people different based on race so we need to fix that and we should keep track of air quality because again, health and yes we should make sure people who vote have the right to vote (although more of us really should vote because we all have a stake in this world) and lead in paint has this really terrible history of hurting people bad and while I don’t understand why some places don’t allow ferrets, even worse I have no idea why my idea of monitoring and regulating firearms better — as in, in such a way that we maybe get less people killed every year — makes me Un-American.
from Instagram https://www.instagram.com/p/BfRfw82FksO/ via IFTTT
Self.
from Instagram https://www.instagram.com/p/BfWnWYclUDH/ via IFTTT
Corgi\Gwen\Del Mar Dog Beach
WordFence is vital for self-hosted WordPress instances.
I’ve been hosting WordPress websites for a long time. This blog I migrated to WordPress in 2004. I had experience with it running San Diego Blog which started on B2 and I converted to WordPress in Summer 2004. So I’ve been hosting WordPress a long time. There’s a reason the software is popular. It’s free, flexible, straightforward to customize, theme, improve, update.
This ease-of-use has brought ubiquity. So much so I attended Creative Mornings San Diego the other morning and one of the sponsors was WordPress. The short description of WordPress included the tagline “powering 25% of websites.”
Ubiquity has made WordPress an extraordinarily attack surface area for hackers. (Like Windows has been for a long time! Yay?!) I’ve seen hacks against user accounts, against the upload feature, I’ve seen worms, and DOS attacks and everything in-between. An absolutely vital tool for me has been WordFence. They’ve done a great job on the free version of the tool. I feel like the paid version is a bit too pricy for my own usage, but WordFence version 7 has been a great update already. This blog has had some targeted SQL injection attacks as well as some suspicious user creation behavior directed at it that WordFence alerted me to and thwarted successfully.
I run several other websites and having WordFence do this kind of work and keeping me up to date keeps my mind at ease.
17 Years And Counting
In 2001 I started blogging via blogger.com. It allowed me to augment my personal site using blog with an external service via FTP and experiment with regularly writing. On this anniversary I have commemorated this before: 2002, 2003, 2004, 2007, 2011, 2014, and 2015.
In 2003 I wrote:
I am at a loss, but it’s not for public condemnation or praise. I would like this blog to be a conduit for finding work and for sharing my thoughts on the technical things which jazz up my life. I also want it, now I realize, as a means to share my experience.
And these many years later that’s pretty much what it’s for. Granted, much of what I do now is cross-post my Instagram posts but still, I’m using this more as my own showcase, for my imperfect self to play with technology.
Just a few months after I started the site here’s what the site looked like when you landed on it, note the blog in the right column:
I’m still learning to blog, and still blogging, and still experimenting.
Most Steps.
I did an export using Pedometer++ and here’s a graph of my steps for the last several years.
That corresponds to a 4 and a half mile walk I took. I’m not sure why there’s an off by one error or why there are so many zero-step days. (Was I bedridden?) But I love the trends, such as they are, regardless.
March Modok Madness is coming!
I never posted about the fact that I did a second MODOK in 2012. I mentioned the first one I did here, but not the second.
What? You’ve never heard of March MODOK Madness?
You’ve never heard of MODOK? Read about him!
from Instagram https://www.instagram.com/p/BfcVJsCFTBT/ via IFTTT
Love 🌷(last week)
Blog Post Visualization + Code
I’ve been doing maintenance galore on this site. I have a hand-written theme and I’ve been doing things like returning the footer to a good shape and sweating the responsive details of it.
I first wrote that code in 2010 but I’ve adapted it to be a bit better and now am using CSS Grid to allow those columns to display a bit better on different screen sizes and form factors.
The header has a similar but not quite the same treatment on archive pages to allow navigating from month to month and year to year quickly.
Like I said, I first wrote the code for the years and months visualization back in 2010.
The PHP code has not changed a great deal from 2010:
<div id="sidebar" class="sidebar-archive"> <?php /* show archive information */ $args = array( 'type' => 'monthly', 'format' => 'custom', 'show_post_count' => true, 'echo' => 0 ); $resulthtml = wp_get_archives($args); $archives = array_map('trim', explode("\n", $resulthtml)); $archiveMonths = array(); foreach($archives as $item) { if (trim($item)!='') { $archiveMonths[] = trim($item); } } $archiveMonths = array_reverse($archiveMonths); $archiveLinks = array(); $yearCount = array(); foreach ($archiveMonths as $link) { // link looks like: // <a href='https://artlung.com/blog/2001/02/' title='February 2001'>February 2001</a> (9) // we want it to look like: // <a href='https://artlung.com/blog/2001/02/' title='February 2001' style='background-position: -9px'>February</a> // and we need the year; // and we need the count; $cssInitial = 400; $temp = explode('</a>', $link); // [0] <a href='https://artlung.com/blog/2001/02/' title='February 2001'>February 2001 // [1] (9) $count = (int)str_replace(array(' (', '('),'',$temp[1]); // 0 ... -400 // 5 ... -395 // 10 .. -390 // 20 .. -380 $cssCount = ($count) - $cssIniital; $year = (int)substr($temp[0],-4); $yearCount[$year] += $count; // $newLink = str_replace('\'>', ", {$count} posts.' style='background-position: {$cssCount}px 0;'>", substr($temp[0], 0, -5)) . "</a>"; $newLink = str_replace('\'>', "' style='background-position: {$cssCount}px 0;'>", substr($temp[0], 0, -5)) . "</a>"; $archiveLinks[$year][] = $newLink;//str_replace($just_text, $month, $link); } foreach ($archiveLinks as $k => $v) { print '<div class="archiveYear">'; print "<h4><a href=\"/blog/{$k}/\" title=\"{$yearCount[$k]} posts in the year {$k}.\">{$k}</a></h4>"; print '<ul><li>' . implode("</li>\n<li>", $v) . '</li></ul>'; print '</div>'; } ?> </div>
And the CSS looks like this:
.sidebar-archive { background-color: #000; display: grid; grid-template-columns: repeat(4, 1fr); } .sidebar-archive .archiveYear { width: 100%; } @media screen and (min-width: 500px) { .sidebar-archive { grid-template-columns: repeat(5, 1fr); } } @media screen and (min-width: 600px) { .sidebar-archive { grid-template-columns: repeat(6, 1fr); } } @media screen and (min-width: 700px) { .sidebar-archive { grid-template-columns: repeat(7, 1fr); } } @media screen and (min-width: 800px) { .sidebar-archive { grid-template-columns: repeat(8, 1fr); } } @media screen and (min-width: 900px) { .sidebar-archive { grid-template-columns: repeat(9, 1fr); } } @media screen and (min-width: 1000px) { .sidebar-archive { grid-template-columns: repeat(10, 1fr); } } @media screen and (min-width: 1100px) { .sidebar-archive { grid-template-columns: repeat(11, 1fr); } } @media screen and (min-width: 1200px) { .sidebar-archive { grid-template-columns: repeat(12, 1fr); } } .archiveYear { width: 100px; background-color: #000; padding: 0; margin: 0; display: inline-block; height: 250px; } .archiveYear h4 { background-color: #000; padding: 15px; margin: 0; color: #fff; text-align: left; font-size: small; font-weight: normal; text-decoration: none; } .archiveYear h4 a { padding: 15px; margin: 0; text-align: left; font-size: small; font-weight: normal; text-decoration: none; color: #fff; } .archiveYear h4 a:visited { color: #fff; } .archiveYear h4 a:hover { color: #fff; } .archiveYear h4 a:link { color: #fff; } .archiveYear h4 a:active { color: #fff; } .archiveYear ul { padding: 0; margin: 0; list-style-type: none; font-size: small; height: 250px; } .archiveYear ul li { padding: 0 15px; text-align: left; } .archiveYear ul li a { text-decoration: none; color: #fff; background-color: blue; display: block; padding: 2px; cursor: pointer; background-image: url(images/black-500x30.gif); background-repeat: no-repeat; }
The source code for all of this is available on GitHub. It also includes the SASS source code for the stylesheets. There are additional notes as well.
If anyone has any questions or comments, please give me a shout!
Suspicious Activity: “An admin user with the username backup was created outside of WordPress”
On 14 February 2018, WordFence alerted me to highly suspicious behavior. This is the format of the email I received from WordFence version 4.9.3:
This email was sent from your website “[REDACTED BLOG NAME]” by the Wordfence plugin.
Wordfence found the following new issues on “[REDACTED BLOG NAME]”.
Alert generated at Wednesday 14th of February 2018 at 12:07:50 PM
Critical Problems:
* An admin user with the username backup was created outside of WordPress.
NOTE: You are using the free version of Wordfence. Upgrade today:
Receive real-time Firewall and Scan engine rule updates for protection as threats emerge
Other advanced features like IP reputation monitoring, country blocking, an advanced comment spam filter and cell phone sign-in give you the best protection available
Remote, frequent and scheduled scans
Access to Premium Support
Discounts of up to 90% for multiyear and multi-license purchases
Click here to upgrade to Wordfence Premium:
https://www.wordfence.com/zz2/wordfence-signup/
This is suspicious on its own, but I wondered if it might be benign. Or at worst, maybe was a plugin gone bonkers. Or maybe my web host was doing something wonky. But strangely, when looking at the accounts in the database I noticed there was no nickname or email address associated with the account. WordPress requires both to create an account if you go through the normal way.
This email was sent from your website “[REDACTED BLOG NAME]” by the Wordfence plugin at Wednesday 14th of February 2018 at 08:28:38 AM
The Wordfence administrative URL for this site is: http://example.org/wp-admin/admin.php?page=Wordfence
A user with username “backup” who has administrator access signed in to your WordPress site.
User IP: 35.183.24.90
User hostname: ec2-35-183-24-90.ca-central-1.compute.amazonaws.com
User location: Montreal, Canada
…then WordFence alerted me this user logged in from an EC2 instance.
Then I got 5 more log-ins in the space of about 10 minutes to other sites I maintain. From the same computer. In my mind, this elevated “suspicious” to “probably malicious.” In that moment I was very glad for my MySQL backup processes that would allow me to go back a few days in time before this nonsense.
The behavior was so swift I wonder about whether it was automated, but logging in with saved credentials is not a terrible slow operation even for a person.
The lack of email address on the accounts implies, to me a concrete plan. No email address means they would have no way to reset their password but also no way for me to track them by email.
I knew I wanted to remove access for this user. So for each I needed to
-
- Change their password
- Log them out
- Add an email address I control for each account
- Change the SALT for the password encryption for each site.
So I did 1, 2, and 3. I used the standard WordPress user administration panel to change each password and log each out. I also added an email address using the gmail “+whatever” format:
Append a plus (“+”) sign and any combination of words or numbers after your email address. For example, if your name was hikingfan@gmail.com, you could send mail to hikingfan+friends@gmail.com or hikingfan+mailinglists@gmail.com.
I kept a list of the sites I was modifying as I went. I also inspected some of the other applications I have hosted to see if there was anything unusual there. Code injections or user creation, for example. I didn’t see anything.
Then I did step 4 for each of the sites. Wordress provides a “SALT CODE GENERATOR” at https://api.wordpress.org/secret-key/1.1/salt/ which gives you a code block suitable for adding to wp-config.php
easily. What is the Salt? I let the WordPress documentation tell you:
In Version 2.6, three (3) security keys, AUTH_KEY, SECURE_AUTH_KEY, and LOGGED_IN_KEY, were added to ensure better encryption of information stored in the user’s cookies. These collectively replaced a single key introduced in Version 2.5.
In Version 2.7 a fourth key, NONCE_KEY, was added to this group. When each key was added, corresponding salts were added: AUTH_SALT, SECURE_AUTH_SALT, LOGGED_IN_SALT, and NONCE_SALT.You don’t have to remember the keys, just make them long, random and complicated — or better yet, use the online generator. You can change these at any point in time to invalidate all existing cookies. This does mean that all users will have to login again.
…
A secret key makes your site harder to hack by adding random elements to the password.
In simple terms, a secret key is a password with elements that make it harder to generate enough options to break through your security barriers. A password like “password” or “test” is simple and easily broken. A random, long password which uses no dictionary words, such as “88a7da62429ba6ad3cb3c76a09641fc” would take a brute force attacker millions of hours to crack. A ‘salt‘ is used to further enhance the security of the generated result.
I’ve not seen any recurrence of the suspicious behavior and have not seen any attempted entry by any of the “backup” accounts created.
There’s no common themes or plugins (other than WordFence and WordPress and my own host) to link the intrusions but I’ll remain vigilant. When I wrote “WordFence is vital for self-hosted WordPress instances” the other day this is the kind of thing I was thinking of.
I reported the behavior to my web host, which they appreciated. I had blocked the IP address for all my sites from that host which they verified I did correctly. They also showed the logs of the logins and other than dates and times not much was useful other than a User-Agent of Mozilla/5.0 (Windows NT 6.1;
.
WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
Because it was an EC2 instance that was at the originating IP address, I also collected my notes on the behavior and reported it to Amazon Web Services: AWS: Report Abuse.
On 21 February 2018 I received replies from Amazon. Not particularly satisfying but it’s my hope they’ll continue to take security seriously.
Hello,
Thank you for submitting your abuse report. We have begun our investigation into the source of the activity or content you reported.
We’ve determined that an Amazon EC2 instance was running at the IP address you provided in your abuse report. We have reached out to our customer to determine the nature and cause of this activity or content in your report.
We will investigate your complaint to determine what additional actions, if any, need to be taken in this case. Due to our privacy and security policies, we cannot provide details regarding the resolution of this case, or the identity of our customer. We may notify you during our investigation if our customer requires more information from you to complete their troubleshooting of the issue. Our customer may reply stating that the activity or content is expected and instructions on how to prevent the activity or manually remove the content, as well. If you wish to provide additional information to us or our customer regarding this case, please reply to this email.
Please note that if we determine the activity or content to not be abusive, we will notify you and resolve the case; we may refrain from communicating further, in that case.
We will notify you once this case has been marked resolved. Thank you for alerting us to this issue.
Regards,
AWS Abuse Team
And also this, which resolves the closes the case out:
Hello,
This is a follow up regarding the abusive content or activity report that you submitted to AWS. We have investigated this report, and have taken steps to mitigate the reported abusive content or activity. Due to our privacy and security policies we are unable to provide details regarding the resolution of this case or the identity of our customer.
We are committed to mediating reports of abusive content or activity to the satisfaction of both the reporters and our customers. If you believe the reported content or activity persists, or are not satisfied with the resolution of this case, please reply directly to this message with more information. Your response should include the most recent activity logs or web location of the content that you have available that indicates that the activity or content persists, as well as a clear, succinct explanation of what you expect of us and our customer.
Thank you for bringing this matter to our attention.
Regards,
AWS Abuse Team
I hope this proves useful to folks. If you’re running self-hosted WordPress, do take a serious look at WordFence.
from Instagram https://www.instagram.com/p/BfgyjyyFPHs/ via IFTTT
Limones 🍋
Markov Chains are hilarious.
I’ve wanted to make Markov chain generated sentences based on this blog for a long while. Wednesday night, I did. It took me under an hour! Why have I avoided it thinking it’d be difficult? Probably I thought it’d take a long time and would be lame.
NOT SO
First, I exported the contents of my blog: Tools > Export
Out of that, you get a complete dump of your site’s content. This is a WordPress eXtended RSS file. What we care about are just two things from each post: the title and the content. To turn this XML into text I wrote a bit of PHP. It parses the <item>
elements and then does a bit of string manipulation to remove all the HTML tags. It then dumps it into a file called “artlung.corpus.txt”.
<?php $xmlstr = file_get_contents("artlung.wordpress.2018-02-22.xml"); $outputfilename = "artlung.corpus.txt"; $blogcontent = new SimpleXMLElement($xmlstr); $all_text = array(); $i = 0; foreach ($blogcontent->channel->item as $item) { $content = $item->children('content', true); $content = str_replace('>', "> ", $content); $content = str_replace('\n', " ", $content); $all_text[] = (strip_tags($item->children('content', true))); $all_text[] = ((string)$item->title); } $str = implode("\n", $all_text); file_put_contents($outputfilename, $all_text); ?>
(I ran this locally on my Mac since I have PHP installed. Did you know you can run a one-line PHP server? Just run php -S localhost:8000
and you have a local web server! I use it all the time. Read about it here.
Then I talked to my friend Kelly and asked her about what library I might use to accomplish this task. She pointed me to NLP (Natural Language Processing) libraries. I did a bit of googling and found Markovify: “a simple, extensible Markov chain generator.” It seems very well documented and the README on GitHub had easy install instructions. I already had python and pip installed and a terminal session with sudo pip install markovify
did the trick.
Once I did that, I created a file “artlungmarkovify.py” and put this in it:
import markovify # Get raw text as string. with open("artlung.corpus.txt") as f: text = f.read() # Build the model. text_model = markovify.Text(text) # Print five randomly-generated sentences for i in range(10): print(text_model.make_sentence()) # Print three randomly-generated sentences of no more than 140 characters for i in range(3): print(text_model.make_short_sentence(140))
Then I ran python artlungmakovify.py
in terminal and BOOM! There’s some not-quite-Joe-Crawford blog sentences (every other sentence italicized to help distinguish the lines):
I expect she’ll be blogging about the interests of governance vs. conservative media in David Frum: Waterloo: I’ve been working at Yahoo has.
Still amazed we made together.
Nobody cares if you know it.
Immersed in his last name while he asked me that if life were these: Joe Crawford | Joe in LeahPeah’s GlassesNice picture, eh?world, meet olivia rex.
When I tend to ramble a bit, pulled nonnative plants, planted native ones.
Also, my feet and went with following the instructions on the NYTimes website Ted Koppel grills FEMA head Mike Brown.
Perhaps in expiating these exhibits we’ll actually find that when in 2004 and 2005.
Roth had a birthday card weighing one pound.
I then loaded up the file into BBEdit and did some cleanup. I removed duplicate lines, removed things like URLs. Sorted all the individual lines. I used BBEdit’s Markup > Utilities > Convert HTML to Text
to undo the HTML entities that were there. I can see that a clean set of sentences are important for getting a good Markov result.
Now I have it generating lines like:
I think of the world of connections: Online social networks are powerful.
I left them in town.
This tension and disquietude sometimes spiral out of steak, chicken, pasta, and pretty much Nazis and haven’t caught on that beach, and the like.
People all over it.
I checked in at the cover here.
I don’t really care for that hair under your belt.
Last Friday, just 3 days to come.
Remembrances all over the weekend.
I’ve been blogging since before I was not particularly interested, but she generally agreed.
But it feels honest to do that, and I’m looking forward to with delight, fear, wonderment.
I’m going to tap my phones and tablets and e-readers shows us that it’s like I’m going to have never met her.
101 in 16 years for a logo, and right there for the stage.
As it is to say, the whole family is way out at subway stops.
My Grandfather retired and they don’t have an original design vinyl giant robot.
I’m doing lots of orange groves back here.
Clever folks will realize you can get to the rock line.
It’s been a few dozen people in this house in which he invited every passerby to lie in the surf, another from yesterday.
The fact that my increased notoriety brings more candy, I expect we won’t get to do serious work.
It will cost $1743 to fix the toilet which was leaking.I have posted in the meantime.A few weeks ago at an unexpected angle – young, white, female and with each player serving in turn.
Yes, San Diego Blog Meetup — Calling all Web Designers in San Diego very dearly.
Who else gets cool Swedish web developers take the train?
But the show must go to the car windows unrolled when the receiver to participate in a much less here.
It was a contest that year to year quickly.
If I finish a silly Flash game I want one of those old images.
It strikes me as a teen, working in Hollywood.
I love this. It’s entertaining silliness.
Now, I sent a few sentences to Leah and she said “it sounds a bit too much like President Trump”–which admittedly made me rather sad. But I can see that with a good corpus some rather interesting things might come out of it. My friend Kelly on reading some results said “It’s very interesting. Like a semantic word cloud.”
It really feels like this century will have more things like this. At some point computers will so good at mimicking us that we won’t be able to tell the difference. What that means for us as a culture? Hard to say.
from Instagram https://www.instagram.com/p/Bfm03oyl6e-/ via IFTTT
So I wrote a bot this past week. It’s a twitter bot (@BloggingBot) & based on my 17 years blogging it makes sentences based on my words. It is surreal to see what it has generated. Because some of them sound like things I might have written. #markovchain #programming #twitterbot
I blogged for 17 years and all I got were these lousy Markov chains.
On Friday I wrote about how I turned 17 years of blog text into interesting sentences. I’ve also put that up on the web at lab.artlung.com/bloggingbot and now, with the help of Cheap Bots Done Quick (a free bot hosting service created by George Buckenham).
I turned that into a Twitter bot that tweets regularly. You can follow it at @BloggingBot.
I really like the code CBDQ uses: Tracery. It’s a straightforward, JavaScript-like syntax that’s kind of fun to write. It’s the brainchild of GalaxyKate.
{ "sentences": ["Here are videos of some of Leah's brothers and sisters.", "Trying to get back on the horse, and I suppose I'm glad I don't get seasick.", // 10,000 lines of pre-generated Markovify sentences "If there are fewer, but still a long way to go. from Instagram IFTTTHere for kind of a joke as a band."], "option": ["You asked for it!", "Here you go!", "Yes indeed!"], "origin" : "#sentences#" }
It’s free to host! Now, previously I’d written about @Ventcheck a bot I wrote at San Diego Code Kitchen in 2016.
BloggingBot can answer a reply made to it, because CBDQ has added that functionality. The reply Tracery code is nice too:
{ "more please":"#option#\n\n#origin#\n\nThanks you for your kind attention. cc @artlung", ".":"Hiya. I'm just a bot. But if you answer with \"more please\" then I'll tweet you again. :-)" }
I submitted it to Mefi Projects yesterday. I look forward to having more projects to submit there. Metafilter is a great community.
So if you feel inclined, please feel free to follow @BloggingBot
I’m enjoying trying to write something technical every day. It’s a challenge that feels doable.
Thanks for your kind attention.
from Instagram https://www.instagram.com/p/BfrvT3NlBkU/ via IFTTT
Leah is cool.
Color the Smiley
Over the years I have made a lot of little web experiments and geegaws. I’ve made hangman games and drawing programs and random text generators. At one place I worked I helped make a thing that would turn an uploaded photo of a face into a Terminator face!
I’ve made so many of these kind of things I don’t always remember I’ve made them. Enter the Smiley!
I remember, vaguely, building this. I don’t have a record of when I did. I include a link to my twitter feed but I can’t find a tweet about it. I joined twitter in 2006 so it could be anytime then. The code is the best source of clues:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
The usage of jQuery 1.4.2 is the tell. Version 1.5 came out on January 31, 2011, and 1.4 was a year earlier. So 2010 is a good bet. 2010 had a lot of things going on. It happens to be the year my mother was so sick, and died. I think that’s why I never wrote about it.
But what about the code?
$(document).ready(function(){ $('#controls span').bind('click mouseover focus', function(){ $(this).siblings().removeClass('selected'); $(this).addClass('selected'); var fig = $('span.selected:lt(3)').text(); var grd = $('span.selected:gt(2):lt(6)').text(); $('div#wrapper, .smiley div.figure').css('background-color', '#' + fig); $('.smiley, .smiley div.ground').css('background-color', '#' + grd); location.hash = '#' + fig + '' + grd; return false; }); var colors = location.hash.split('#')[1]; for(var i=0;i<colors.length;i++){ $('div.segment div:eq('+i+') span:contains('+colors.substr(i,1)+')').trigger('click'); } }); </script>
The code is not bad! It does the job, it uses idiomatic jQuery in a way I might today. I’d probably organize the whole thing differently now but it’s a fun little snippet. These days I might play with in such a way that you could share the silly smiley with people on social media. I might add a feature to turn it into an image. I might change the interaction a bit – I do have the numerical color value buttons respond to mouseover and click, so users on a phone or tablet don’t have a bad time. I also made it very narrow, also friendly to phones of the time.
Now, I can tell by the CSS I didn’t use SASS or any other CSS Preprocessor so that’s a bummer there. I also think I’d organize the code in a more MVC way so that the color model could be reused for something else.
Thanks for reading.