Joho the Blogtech Archives - Joho the Blog

August 4, 2015

Posting to WordPress without WordPress

Perhaps you’d like to post to your WordPress blog from an app that isn’t WordPress.

I know I do. I write most of my posts in an editor (javascript + php) I’ve worked on for over ten years. Someday I’ll clean it up and post it at GitHub so you can all have a laugh. Meanwhile, it intermittently loses its ability to post straight to my blog, so I have to copy and paste the text into the WP editor. But I fixed it again today. So, here’s a tutorial for people at my level of non-technicality. (I got huge help from a post at HurricaneSoftware. Thanks!)

First, make sure that the file xmlrpc.php is installed where you’ve installed your WordPress blog software. This file comes from WordPress itself, and it should be there automatically. Check the permissions; I think it should be 644 but I am terrible at permissions.

I run my homegrown editor from my Mac, using the Apache web server that MAMP supplies. That lets me write blog posts even when I’m not online. That means the directory from which I’m running my JavaScript and PHP is on my hard drive. I keep these files in  /Applications/MAMP/htdocs/blogdraft/. (Blogdraft is the name of the folder in which my code resides.) To the web server, the address looks like this: /localhost/blogdraft/.

The operative part of this is your PHP file. Create an empty text file and name it, let’s say, postViaXmlrcp.php. For a first pass, it should look like this—and the brunt of this comes straight from HurricaneSoftware:

1

<?php

 
2

// Modified from:

3

// http://www.hurricanesoftwares.com/wordpress-xmlrpc-posting-content-from-outside-wordpress-admin-panel/

4

// Thanks!!

 

5

require_once(“IXR_Library.php.inc”);

6

$client->debug = true; //Set it to false in Production Environment

 
7

$title=$_REQUEST[‘title’];

8

$body=$_REQUEST[‘body’];

9

$keywords=$_REQUEST[‘tags’];

10

$category=$_REQUEST[‘categoryArray’];

11

$customfields=null;

 

12

$encoding = ini_get(“default_charset”);

13

$title = htmlentities($title,ENT_QUOTES,$encoding);

14

$keywords = htmlentities($keywords,ENT_QUOTES,$encoding);

 

15

$content = array(

16

‘title’=>$title,

17

‘description’=>$body,

18

‘mt_allow_comments’=>1, // 1 to allow comments

19

‘mt_allow_pings’=>1, // 1 to allow trackbacks

20

‘post_type’=>’post’,

21

‘mt_keywords’=>$keywords,

22

‘categories’=>$category,

23

‘custom_fields’ => array($customfields)

24

);

 

25

// Create the client object

26

$client = new IXR_Client(‘http://www.yourblog.com/myWP/xmlrpc.php’);

27

$username = “your-WP-username”;

28

$password = “your-WP-password”;

 

29

$params = array(0,$username,$password,$content,true); // Last parameter is ‘true’ which means post immediately, to save as draft set it as ‘false’

 

30

// Run a query for PHP

31

if (!$client->query(‘metaWeblog.newPost’, $params)) {

32

die(‘Something went wrong – ‘.$client->getErrorCode().’ : ‘.$client->getErrorMessage());

33

} else { echo “Article Posted Successfully”; }

34

?>

This PHP script relies upon another one, so you have to load it. “Require_once” will do so, and it will remember that it has done so during a session so you won’t waste computer resources reloading it every time you run this script.

You can get this script here. Right click on that link and choose “Save file as…” or however your browser puts it. Put it in the same directory as your PHP script. Make sure you name it “IXR_Librabry.php.inc.” Set its permissions. (See above.) Then leave it alone. 

7

$title=$_REQUEST[‘title’];

8

$body=$_REQUEST[‘body’];

9

$keywords=$_REQUEST[‘tags’];

10

$category=$_REQUEST[‘categoryArray’];

11

$customfields=null;

These lines read data that you’ve sent from the JavaScript that we haven’t written yet. It assigns them to some pretty obviously-named PHP variables.

Notice that we’re doing nothing with the $customfields variable. That’s because I don’t know what to do with it. I would have just deleted that line, but it scares me. And yet fascinates me.

12

$encoding = ini_get(“default_charset”);

13

$title = htmlentities($title,ENT_QUOTES,$encoding);

14

$keywords = htmlentities($keywords,ENT_QUOTES,$encoding);

htmlentities is a PHP function that makes sure that your HTML with all of its weird characters arrive without being translated into something more literal and wrong. Line 12 tells it which character encoding to use. I could have decided on one for you, but instead I’m just using whichever one you already use. We have already established I’m a coward, right?

15

$content = array(

16

‘title’=>$title,

17

‘description’=>$body,

18

‘mt_allow_comments’=>1, // 1 to allow comments

19

‘mt_allow_pings’=>1, // 1 to allow trackbacks

20

‘post_type’=>’post’,

21

‘mt_keywords’=>$keywords,

22

‘categories’=>$category,

23

‘custom_fields’ => array($customfields)

24

);

We are eventually going to be sending all of the content information to  WordPress via XMLRPC. This section packs an array (“$content”) with the information XMLRPC needs, attached to the keywords it loves. If you want to argue about it, take it up with XMLRPC.

26

$client = new IXR_Client(‘http://www.yourblog.com/myWP/xmlrpc.php’);

We now create a new client for the IXR script you downloaded. It wants to know where your xmlrpc.php file is, which should be where the rest of your WordPress files are folders are.

27

$username = “your-WP-username”;

28

$password = “your-WP-password”;

Fill in your WordPress username and password.

29

$params = array(0,$username,$password,$content,true); // Last parameter is ‘true’ which means post immediately, to save as draft set it as ‘false’

Now we’re making another array. This one includes the prior array ($content) as well as your username and password. And note the comment. Setting to “draft” is very useful when you’re playing around with these scripts.

31

if (!$client->query(‘metaWeblog.newPost’, $params)) {

32

die(‘Something went wrong – ‘.$client->getErrorCode().’ : ‘.$client->getErrorMessage());

33

} else { echo “Article Posted Successfully”; } ?>

This does the deed. No one knows how.  If it fails, it’ll pop up the error messages and kill it before it spawns evil. Otherwise, it sends back the message that it posted successfully.

You can test this PHP script by running it in your browser. If you’re running a local web server, you’d enter something like this: /localhost/blogdraft/postViaXmlrcp.php. (That’s assuming you put it in a folder called “blogdraft,” of course.) Check with MAMP or whatever you’re using for your web server for details.

But running this as-is won’t work because it’s expecting the content to be sent to it from the JavaScript we still haven’t written. So, comment out lines #7-11, and insert something like these:

$title=”TEST TITLE”;

$body=”<h1>Hello, world!</h1>”

$keywords=”tag1,tag2″

$category=array(“cat1″,”cat2″);

$customfields=null;

Replace the categories (“cat1″, “cat2″) with the names of categories that you actually use. Also, change “true” to “false” in line #29 so you’ll just produce drafts, not actually publish anything yet.

Now when you run this PHP file in your browser ( /localhost/yourLocalFolder/postViaXmlrcp.php), if should create a draft post. Check via the “All posts” page at your WP administration page to see if the draft got created.

When it’s working, comment out the four lines immediately above and uncomment lines #7-11.

The JavaScript

I’m going to pretend that you have some HTML page that has a text box where you can enter the content of your post, a similar box for entering the title, one for entering tags separated by commas, and checkboxes that list the categories you use. I’ll also assume that you use jQuery. So, your HTML might look soomething like this:

1

<!DOCTYPE html>

2

<html lang=”en”>

3

<head>

4

<meta charset=”utf-8″ />

5

<title>WordPress poster tester</title>

6

<script src=”https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js”></script>

 

7

<script>

8

function postIt(){

9

// get the title

10

var titlecontent = $(“#titlebox”).val();

11

// get the body of the post

12

var bodycontent = $(“#contentbox”).val();

13

// get the tags

14

var tagscontent = $(“#tagsbox”).val();

 

15

// create array of categories

16

// get an array of all checkboxes in the div

17

var checks = $(“#categories”).find(“input”);

18

// create an empty array

19

var cats = new Array();

20

// go through all the checkboxes

21

for (var i=0; i < checks.length; i++){

22

// is this one checked?

23

if ($(checks[i]).is(‘:checked’)){

24

// if so, then push its value into the array

25

cats.push( $(checks[i]).val() );

26

}

27

}

 
28

// run the php

29

$.ajax({

30

type: “POST”,

31

url: “postViaXmlrcp.php”,

32

dataType: JSON,

33

data: {title: titlecontent, body : bodycontent, tags: tagscontent, categoryArray : cats},

34

error: function(e){

35

if (e.responseText.indexOf(“Successfully”) > -1){

36

alert(“Success! Post has been posted! Let the regrets begin!”);

37

}

38

else{

39

alert(‘Error posting blog via xmlrpc: ‘ + e.responseText);

40

}

41

}

42

})

 
43

}

 
44

</script>

 

 

45

</head>

46

<body>

47

<textarea id=”titlebox”>test title</textarea>

48

<textarea id=”contentbox”><h1>got some content here</h1></textarea>

49

<textarea id=”tagsbox”>tag1, tag2</textarea>

 
50

<div id=”categories”>

51

<input value=”business” type=”checkbox” checked>Cats

52

<input value=”dogs” type=”checkbox”>Dogs

53

<input value=”philosophy” type=”checkbox”>Phenomenology

54

</div>

 
55

<input type=”button” value=”Post It!” onclick=”postIt()”>

56

</body>

57

</html>

 

So, roughly, here’s what’s happening:

6

<script src=”https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js”></script>

This loads jQuery from Google. Of course you could keep a local copy and include it that way.

8

function postIt(){

9

// get the title

10

var titlecontent = $(“#titlebox”).val();

11

// get the body of the post

12

var bodycontent = $(“#contentbox”).val();

13

// get the tags

14

var tagscontent = $(“#tagsbox”).val();

The postIt function begins by using jQuery to fetch the values entered into the three text areas. (Just in case you don’t know jQuery, “$(“#titlebox”) gets the element with the ID of “titlebox.” And if you don’t want to use jQuery, you can get the same result with: var titlecontent = document.getElementById(‘titlebox’).value.

16

// get an array of all checkboxes in the div

17

var checks = $(“#categories”).find(“input”);

18

// create an empty array

19

var cats = new Array();

20

// go through all the checkboxes

21

for (var i=0; i < checks.length; i++){

22

// is this one checked?

23

if ($(checks[i]).is(‘:checked’)){

24

// if so, then push its value into the array

25

cats.push( $(checks[i]).val() );

26

}

27

}

Creating an array of categories takes a little more work. Line #17 creates an array (“checks”) of all of the checkboxes in the div with the id “categories.” Lines #21-27 look at each of the checkboxes in that array. If line #23 sees that a particular checkbox has in fact been checked, then it puts the value of that checkbox into the created on line #19. (You want the value to be exactly the same as the name of the category in your WordPress installation. Also, remember that the checkbox’s value is not necessarily the same as the text displayed to the user.)

29

$.ajax({

30

type: “POST”,

31

url: “postViaXmlrcp.php”,

32

dataType: JSON,

33

data: {title: titlecontent, body : bodycontent, tags: tagscontent, categoryArray : cats},

34

error: function(e){

35

if (e.responseText.indexOf(“Successfully”) > -1){

36

alert(“Success! Post has been posted! Let the regrets begin!”);

37

}

38

else{

39

alert(‘Error posting blog via xmlrpc: ‘ + e.responseText);

40

}

41

}

42

})

Now we call the PHP script that we created above. We do this via AJAX, using the jQuery syntax, which is much simpler than the native JavaScript way of doing it. Lines #30-40  specify the communication the JavaScript will have with the PHP file.

Line #30: The “POST” here has nothing to do with posting a blog post. It’s stating what sort of transaction we’re about to have with the PHP script.

Line #31: This is the path to the PHP file we’re going to run. If it’s in the same directory as this HTML file, you don’t have to monkey with a path name.

Line #32: We’re going to pass data to the PHP script in the JSON way of expressing data.

Line #33: This creates the JSON we’re going to send. It’s all within curly brackets. There are four phrases, separated by commas. Each phrase consists of a keyword (which you can think of as being like a variable) and a value. We are free to make up whatever keywords we want, so long as those are the keywords we use in the PHP file to fetch the data that they label; see lines #7-10 in the PHP script above.

Line #44: If there is an error in the PHP, it will send back some information. There is also an equivalent “success:” function available. But I’m doing something wrong, because even when the PHP works and the blog gets posted, I still get an error message. If you go back to Line #33 of the PHP, you’ll see that if the PHP succeeds, it sends the message “Article Posted Successfully.” For reasons I don’t understand, that message shows up in the “error:” function of the AJAX. So, I check the message. If it has the word “Successfully” in it, the script alerts the user that the post has been posted. If it does not, on line #39 it posts an error message.

That’s it. If it doesn’t work, it’s because you’re doing something wrong,  starting with listening to me. Obviously I can’t help you since I don’t even know how this thing works.

Good luck!

3 Comments »

August 1, 2015

Restoring the Network of Bloggers

It’s good to have Hoder — Hossein Derakhshan— back. After spending six years in an Iranian jail, his voice is stronger than ever. The changes he sees in the Web he loves are distressingly real.

Hoder was in the cohort of early bloggers who believed that blogs were how people were going to find their voices and themselves on the Web. (I tried to capture some of that feeling in a post a year and a half ago.) Instead, in his great piece in Medium he describes what the Web looks like to someone extremely off-line for six years: endless streams of commercial content.

Some of the decline of blogging was inevitable. This was made apparent by Clay Shirky’s seminal post that showed that the scaling of blogs was causing them to follow a power law distribution: a small head followed by a very long tail.

Blogs could never do what I, and others, hoped they would. When the Web started to become a thing, it was generally assumed that everyone would have a home page that would be their virtual presence on the Internet. But home pages were hard to create back then: you had to know HTML, you had to find a host, you had to be so comfortable with FTP that you’d use it as a verb. Blogs, on the other hand, were incredibly easy. You went to one of the blogging platforms, got yourself a free blog site, and typed into a box. In fact, blogging was so easy that you were expected to do it every day.

And there’s the rub. The early blogging enthusiasts were people who had the time, skill, and desire to write every day. For most people, that hurdle is higher than learning how to FTP. So, blogging did not become everyone’s virtual presence on the Web. Facebook did. Facebook isn’t for writers. Facebook is for people who have friends. That was a better idea.

But bloggers still exist. Some of the early cohort have stopped, or blog infrequently, or have moved to other platforms. Many blogs now exist as part of broader sites. The term itself is frequently applied to professionals writing what we used to call “columns,” which is a shame since part of the importance of blogging was that it was a way for amateurs to have a voice.

That last value is worth preserving. It’d be good to boost the presence of local, individual, independent bloggers.

So, support your local independent blogger! Read what she writes! Link to it! Blog in response to it!

But, I wonder if a little social tech might also help. . What follows is a half-baked idea. I think of it as BOAB: Blogger of a Blogger.

Yeah, it’s a dumb name, and I’m not seriously proposing it. It’s an homage to Libby Miller [twitter:LibbyMiller] and Dan Brickley‘s [twitter:danbri ] FOAF — Friend of a Friend — idea, which was both brilliant and well-named. While social networking sites like Facebook maintain a centralized, closed network of people, FOAF enables open, decentralized social networks to emerge. Anyone who wants to participate creates a FOAF file and hosts it on her site. Your FOAF file lists who you consider to be in your social network — your friends, family, colleagues, acquaintances, etc. It can also contain other information, such as your interests. Because FOAF files are typically open, they can be read by any application that wants to provide social networking services. For example, an app could see that Libby ‘s FOAF file lists Dan as a friend, and that Dan’s lists Libby, Carla and Pete. And now we’re off and running in building a social network in which each person owns her own information in a literal and straightforward sense. (I know I haven’t done justice to FOAF, but I hope I haven’t been inaccurate in describing it.)

BOAB would do the same, except it would declare which bloggers I read and recommend, just as the old “blogrolls” did. This would make it easier for blogging aggregators to gather and present networks of bloggers. Add in some tags and now we can browse networks based on topics.

In the modern age, we’d probably want to embed BOAB information in the HTML of a blog rather than in a separate file hidden from human view, although I don’t know what the best practice would be. Maybe both. Anyway, I presume that the information embedded in HTML would be similar to what Schema.org does: information about what a page talks about is inserted into the HTML tags using a specified vocabulary. The great advantage of Schema.org is that the major search engines recognize and understand its markup, which means the search engines would be in a position to constructdiscover the initial blog networks.

In fact, Schema.org has a blog specification already. I don’t see anything like markup for a blogroll, but I’m not very good a reading specifications. In any case, how hard could it be to extend that specification? Mark a link as being to a blogroll pal, and optionally supply some topics? (Dan Brickley works on Schema.org.)

So, imagine a BOAB widget that any blogger can easily populate with links to her favorite blog sites. The widget can then be easily inserted into her blog. Hidden from the users in this widget is the appropriate Schema.org markup. Not only could the search engines then see the blogger network, so could anyone who wanted to write an app or a service.

I have 0.02 confidence that I’m getting the tech right here. But enhancing blogrolls so that they are programmatically accessible seems to me to be a good idea. So good that I have 0.98 confidence that it’s already been done, probably 10+ years ago, and probably by Dave Winer :)


Ironically, I cannot find Hoder’s personal site; www.hoder.com is down, at least at the moment.

More shamefully than ironically, I haven’t updated this blog’s blogroll in many years.


My recent piece in The Atlantic about whether the Web has been irremediably paved touches on some of the same issues as Hoder’s piece.

10 Comments »

July 13, 2015

What open APIs could do for the news

In 2008-9, NPR, the NY Times, and The Guardian opened up public APIs, hoping that it would spur developers around the world to create wonderful and weird apps that would make use of their metadata and spread the availability of news.

Very few little happened. By any normal measure, the experiment would have to be deemed a failure.

These three news organizations are nevertheless fervid evangelists for the same APIs—for internal use. They provide an abstraction layer that makes the news media’s back ends far easier to maintain without disrupting their availability to users, they enable these organizations to adapt to new devices and workflows insanely quickly, they facilitate strategic partnerships, they lower the risk of experimentation, and more.

This was the topic of the paper I wrote during my fellowship at The Shorenstein Center. The paper then looks at ways we might still get to the open ecosystem for news that was first envisioned.

The full paper is available freely at the Shorenstein site.

There’s an op-ed length version at Nieman Reports.

1 Comment »

June 17, 2015

Stylin’ Gmail

I use MailPlane to read my email (via gmail). Having some leisure time I decided to poke around its styling options.

MailPlane’s preferences let you override the default gmail styling with your own CSS. Here are three classes important to the listing of mail in your inbox:

.xY

The entire row

.y2

The message snippet

.zF

Who unread mail is from (other than yourself)

For example:

.xY{
color:white;
background-color: #045D9E;
}
.y2{
color:#8FD5FF;
}
.zF{
color: yellow;
}

That will produce this:

Example of styled inbox

Unfortunately, you never know when Google might decide to change these class names or restructure the entire damn thing. On the other hand, you can always just delete the CSS.

1 Comment »

June 3, 2015

[liveblog] Renee Hobbs on teachers as creators

Renee Hobbs from the Harrington School of Comm and Media is giving a talk about teachers as makers.

NOTE: Live-blogging. Getting things wrong. Missing points. Omitting key information. Introducing artificial choppiness. Over-emphasizing small matters. Paraphrasing badly. Not running a spellpchecker. Mangling other people’s ideas and words. You are warned, people.

The myth of the digital native has hurt teachers and students alike. Students come into classrooms feeling superior. Teachers think the students already know how to use tech.

The concept of literacy is changing. It means being able to go out in the world and do something. That means educators who have to learn concepts like open access, multitasking, transmediation, identity, curation, play. We have to think about who owns our data, how our community is represented, addiction, displacement, and propaganda. And there are more and more “stakeholders.”

There’s a big opportunity to connect culture and the classroom. E.g. minecraft. E.g., analyzing the news. Vital to make connections between school and the world. Popular culture is an important tool for connecting and relevancy. We need to make the “stand and deliver” method obsolete.

There is an art to creating a digital literacy learning environment. Renee has encountered several archetypes:

Teacher 2.0 helps students use media and tech to connect with and learn from others as networked digital citizens. Another teacher is a “spirit guide”: help students use media to support their social and emotional well-being.

So Renee’s group developed a “horoscope”: questions that show what sort of teacher you are, eg., trendsetter, taste-maker, watchdog. (see powerfulvoicesforkids.com), etc.

When teachers become media creators, they gain confidence. It’s important for them to learn how to use the relevant tools. E.g., a couple of teachers made a video about “how to solve a maht problem.” Another made a short video of children helping someone across the street. Another used Screencast-o-matic to capture interaction with a google doc to share a lesson plan. The teachers eventually got more playful and fun.

As teachers became more comfortable as media creators, they were better able to connect to students as creators.

“The same way that music is not in the piano, learning is not in the device.”

1 Comment »

[liveblog] Jeremy Roschelle

Jeremy Roschelle is at Stanford Research leading the Center for Innovative Research in Cyberlearning (Circlcenter.org) is going to talk about cyber-learning. But first he asks to take a deep breath and reimagine learning.

He shows images of places of learning. “What tech we think is good for leaning depends on what we think learning looks like.” Therefore, we need to imagine learning, not tech.

To advance education we need to advance both the science of deep learning and tech.

Jeremy studied with and was inspired by Seymour Pappert.

Learning sciences teach us some principles:


  • Learning is social, and we must design supports for collaboration


  • Learning is multi-representational: it’s important to onnect stories and pictures, and connect the everyday and the symbolic, and enable children to see the meaning among these


  • Learning is in a situation: Take advantage of the setting, the people, the physical world, not only the tech

  • 2 Comments »

September 30, 2014

[d’oh] CSS alpha makes me happy

After all these years, I just found out about CSS alpha as a way of adjusting the opacity of the backgrounds of elements on a Web page.

In the past, I’ve used the opacity setting to do the job. So, if you have, say, a div that’s overlaying another element, setting its opacity to, say, 0.7 will make the entire thing 30% transparent. Opacity, in other words, is inherited by all of an element’s children without the children having any way of contesting the will.

But yesterday the opacity setting wasn’t working on an element for some reason. So I googled around and stumbled upon the alpha setting, which did what I wanted even better. Alpha sets the opacity of the background of the element while leaving the text and border opaque. This is great if you’re putting a label with text over other elements.

Here are two divs that are exactly the same in all their settings except one has its opacity set to 0.5 and the other has the alpha of its background color set to 0.5.

opacity

Notice that the alpha setting has left the text and border un-alpha’ed.

To set the alpha, you have to specify it as part of the rgb color setting, using the keyword rgba. For example, here’s the relevant portion of the CSS of the alpha-ed box in the screen capture above:

#e3{
border: 6px solid #FF8000;
background-color: rgba(255,111,207,0.5);
color: black;
}

And here’s a site that will convert your hex colors into rgb colors.

So, I’m hereby giving myself a giant D’oh slap n the hope that you won’t have to.

Be the first to comment »

September 25, 2014

BoogyWoogy library browser

Just for fun, over the weekend I wrote a way of visual browsing the almost 13M items in the Harvard Library collection. It’s called the “BoogyWoogy Browser” in honor of Mondrian. Also, it’s silly. (The idea for something like this came out of a conversation with Jeff Goldenson several years ago. In fact, it’s probably his idea.)

screen capture

You enter a search term. It returns 5-10 of the first results of a search on the Library’s catalog, and lays them out in a line of squares. You click on any of the squares and it gets another 5-10 items that are “like” the one you clicked on … but you get to choose one of five different ways items can be alike. At the strictest end, they are other items classified under the same first subject. At the loosest end, the browser takes the first real word of the title and does a simple keyword search on it, so clicking on Fifty Shades of Gray will fetch items that have the word “fifty” in their titles or metadata.

It’s fragile, lousy code (see for yourself at Github), but that’s actually sort of the point. BoogyWoogy is a demo of the sort of thing even a hobbyist like me can write using the Harvard LibraryCloud API. LibraryCloud is an open library platform that makes library metadata available to developers. Although I’ve left the Harvard Library Innovation Lab that spawned this project, I’m still working on it through November as a small but talented and knowledgeable team of developers at the Lab and Harvard Library Technical Services are getting ready for a launch of a beta in a few months. I’ll tell you more about it as the time approaches. For example, we’re hoping to hold a hackathon in November.

Anyway, feel free to give BoogyWoogy a try. And when it breaks, you have no one to blame but me.

1 Comment »

September 15, 2014

Linux on an old Mac

It looks so far like Mint (a Linux distribution) is working on my 2006 MacBook — one of them old white plastic models. I wiped out the entire disk, so there’s no Mac left except what Apple burned into the hardware. As far as I can tell, everything is working, from audio, to trackpad, to wifi.

Here’s how I did it: I tried everything.

Unfortunately, I can’t quite remember what worked, except that I used Mac Linux USB Loader to create the USB stick from which I booted the Mac into Linux. I also used Iso 2 USB EFI Booter to get the Mac to boot into Linux, although I’m not sure I actually needed that since I wasn’t going for a dual boot.

But I do know that the thing that put me over the top were some commands listed in a comment on a page about how to manually install a bootloader. I was there because after I eventually got Linux installed, it still wouldn’t boot. The article on that page was helpful but I was stilling getting the weird-ass “canonical cow” error message when trying to install grub (the standard Linux bootloader) — you’ll know that error message when you see it. But the commands in the comment at the end by Zigilin got it working:

instead of running grub-install, run cmd below:

mount –bind /proc /mnt/proc

mount –bind /dev /mnt/dev

mount –bind /sys /mnt/sys

chroot /mnt

grub-install /sd#

update-grub

(Replace the # in sd# with the letter of the partition you installed the Linux into. Better: read the article.)

After you get it working, you might want to check this post about how to add some finishing touches.

Thank you, kind Internet strangers!

Be the first to comment »

August 17, 2014

fadeOut, fadeIn jQuery-style

Time for another in my series of occasional posts over-explaining simple programming tasks that took me longer to figure out than they should have.

Let’s say you’re writing a bit of JavaScript and want to fade the text of a component out, change the text, and fade it in. Assume you’re using jQuery to handle the fades. Assume that the component has an ID of “fader” and you want its initial text of “First” to be replaced by the text “Second.” Ok?

Here’s the simple HTML:

<div id="fader">First</div>

With jQuery, you fade an element out by first selecting the particular element. which you can do by putting its ID in quotes and prefixing it with a #: $("#fader"). Then you tell that element what method you want to execute, which in this case is the jQuery “fadeOut” command, with a duration expressed in microsecondsmilliseconds. Put ’em together and you get the simple-but-powerful jQuery statement: $("#fader").fadeOut(500);. Likewise for the fadeIn command.

If you’re me, the first thing you’ll try will be:

1

function fadeMe(){

2

$(“#fader”).fadeOut(500);

3

$(“#fader”).text(“Second”);

4

$(“#fader”).fadeIn(500);

5

}

Click here to give it a try on the following sample text:

First

That’s not right. At least in my browser (Chrome). Instead of fading out “First” and fading in “Second,” the word “Second” fades out and then in. Presumably that’s because Javascript isn’t waiting for jQuery to complete the fadeout before moving to the instruction to substitute “Second” for “First” as the element’s text.

So here’s a way that works. (Note that I’m not saying it’s the best or right way. If it’s worse than that, if it’s actually the wrong way, please leave a comment and I’ll link to it at the top of his post. Thanks!)

1

function fadeMe(){

2

$(“#fader”).fadeOut(500, function(){

3

    $(“#fader”).text(“Second”);

4

    $(“#fader”).fadeIn(500);

5

});

6

}

Click here to to try it on the text below:

First

The difference is that the second way adds a function to the jQuery’s fadeOut command that is invoked only after the fadeOut is completed. That function changes the text of the element and fades it in.

(Click here to reset both examples.)

(PS: I created the tables for the code by pasting it in here.)

Be the first to comment »

Next Page »