📜 ⬆️ ⬇️

Writing an HTML widget for the iBook Author application

It's no secret that printed books are a thing of the past. They are being replaced by a new generation of devices (and programs with them), which allow not only to read the material, like a book, but also to diversify reading with interactive inserts. It can be like some dynamically changing material (twitter tape, etc.), or some interactive content (animation of condenser, etc.)
Apple has released the iBook Author application, which allows you to create interactive books for the iBooks application for ipad devices. Today, I propose to get acquainted with how to create HTML widgets for this application on the example of the Twitter widget.
To create widgets there are many programs, the cost of which varies from 0 (Dashcode) to 60 ( Tumult Hype ).
We will create our own widget “manually”, without using specialized programs.
Now I propose to move from words to deeds.

Widget structure



HTML widget for iBook is a folder with wdgt extension.
When creating an HTML widget, you can select the following required files:

')

Info.plist - what's in the config?


This config file is nothing more than an xml file, in which parameters are written as
<key></key> < ></ > 


Parameters used:

The use of these parameters will be sufficient to create the first widgets.

Now let's proceed directly to the implementation of the widget.

Directly widget implementation


Planning a widget job

In order for the author to control the widget, let's take the initial conditions:
  1. When the widget starts, it sends a request to the server, gets a list of users \ hashtags that should display
  2. Generates data in the “format” needed for twitter
  3. "Import" Twitter API script, waiting for its response
  4. Decorates data in a user-friendly view

In this widget we will use the jQuery library (to simplify working with JSON and create AJAX requests)

Html file

It is not a “practical” use in this example. Contain a container for future tweets:
 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <script type="text/javascript" src="jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="style.css"/> </head> <body> <input type="hidden" id="ID" value="SomeWidgetIDForServerQuery" /> <div id='tweet-container'> </div> <script type="text/javascript" src="ServerQuery.js"></script> </body> </html> 

JavaScript stuffing

The main task of the script will be sending AJAX requests to servers. There is one limitation here. In direct form, such requests can not be sent to us. More precisely, the request will go to the server, the server will process it, but the widget will not be able to accept the data. Therefore, the way out of this situation is to use JSONP.
What it is? This is a pattern that will allow us to send data to a remote server and “bypass” the domain restriction policy.
What does this method look like?
The widget creates a GET request, in the parameters of which (besides the necessary information) indicates the callback function. The server returns data wrapped into a javascript function call in the format
 callback-(   JSON); 


Define the data that the server will send: let's say the data will contain only one parameters parameter, which will be represented as an array of name elements (including both users and hashtags)
Sample server response:
 jsonp_callback({"results":[{"name":"user1"},{"name":"#hashCode1"}]}); 

Let's write a script that will make a request to the server and process the received data, transferring it to the “necessary” format for twitter:
(the format is simple - user tweets are defined as from: user, the connection between various search filters is performed using "+ OR +", hash tags do not change except for # transfer to the character% 23)

 //       var requestStr = ""; //  " "    function PrepareItem(item) { if (requestStr != "") requestStr += '+OR+'; if (item[0] != "#") {//     requestStr += 'from:' + item; } else {//   - requestStr += '%23'; for (var index = 1; index < item.length; index++) requestStr += item[index]; } } $(document).ready(function() { $.ajax({ //    dataType: 'jsonp', jsonp: 'jsonp_callback', // GET       -callback url: "http://mySite.ru/widgets/twitter.php", data: { ID:$('#ref').val() }, success: function( result ) { $(result.results).each(function(item) { PrepareItem(item.name); }); //    (    ) CreateQueryToTwitter(requestStr); } }); 


However, JSONP assumes the second method of data transfer (physically it does not differ from the first one - the difference is only in software implementations) - it is the second method that we will use to send the request to Twitter.

This method consists of adding a script element to HTML, whose body is empty, and src contains the same GET request indicating the callback function and other parameters.

After sending the request, we just have to parse the Twitter response (the most useful information is in the results element) and format it.
 function CreateQueryToTwitter(request) { var newScript = document.createElement('script'); newScript.setAttribute("type", "text/javascript");//  newScript.setAttribute("src", "http://search.twitter.com/search.json?q=" + request + "&callback=tweetResponse&rpp=40"); //   HTML  document.getElementsByTagName("head")[0].appendChild(newScript); } function tweetResponse(result) { var container=$('#tweet-container'); container.html(''); //  $(result.results).each(function () { var str = (' <div class="tweet">\ <div class="avatar"><a href="http://twitter.com/'+this.from_user+'" target="_blank"><img src="'+this.profile_image_url+'" alt="'+this.from_user+'" /></a></div>\ <div class="user"><a href="http://twitter.com/'+this.from_user+'" target="_blank">'+this.from_user+'</a></div>\ <div class="txt">' + formatTweet(this.text) + '</div>\ '); container.append(str); }); } //   ,     function formatTweet(str) { str=' '+str; str = str.replace(/((ftp|https?):\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?)/gm,'<a href="$1" target="_blank">$1</a>'); str = str.replace(/([^\w])\@([\w\-]+)/gm,'$1@<a href="http://twitter.com/$2" target="_blank">$2</a>'); str = str.replace(/([^\w])\#([-,-,az,AZ,\-]+)/gm,'$1<a href="http://twitter.com/search?q=%23$2" target="_blank">#$2</a>'); return str; } 


It remains only to register the styles for the widget and the HTML code is ready:
 body { font-family: Tahoma,Arial,Verdana,sans-serif; width:1024px; margin: auto; height:768px; } #tweet-container { overflow-y:scroll; height:768px; width:660px; margin: auto; } .tweet { color:black; margin-top:5px; background-color:#F0F1F4; border-bottom:3px solid #5ea8de; padding:10px; margin-left:5px; width:600px; height:autopx; } .avatar { float:left; } .avatar:hover { opacity:0.5; } .user { float:left; padding-left:10px; } .user a { text-decoration:none; color:black; font-size:1.1em; } .user a:hover { color:#DB4FDB } .txt { clear:left; } 


Now add the file Info.plist to this webpage. In my widget, it looks like this:
  <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>BackwardsCompatibleClassLookup</key> <true/> <key>CFBundleDevelopmentRegion</key> <string>Russian</string> <key>CFBundleDisplayName</key> <string>twitter</string> <key>BRNotifiesOnReady</key> <true/> <key>CFBundleIdentifier</key> <string>ru.mySite.widget.twtter</string> <key>CFBundleName</key> <string>twitter</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1.0</string> <key>KFNotifiesOnReady</key> <false/> <key>Height</key> <integer>768</integer> <key>MainHTML</key> <string>main.html</string> <key>Width</key> <integer>1024</integer> <key>IBNotifiesOnReady</key> <false/> </dict> </plist> 


Thus, it remains only to rename the folder by adding the .wdgt extension to it and it can be safely used in the Ibook Authors.

Finally


In this how-to, I tried to make out the steps of creating the simplest widget and describe the most “dangerous” places, such as the connection of the widget with the server. Of course, if you remove the connection of the widget with a certain server, which assigns names and hash tags to it and writing them in the widget, you can reduce the number of dependencies of this widget.

I hope this article does not just take your time, but it will be something useful. :)

Source: https://habr.com/ru/post/171141/


All Articles