-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml
605 lines (435 loc) · 35.2 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Patrick Canella</title>
<description>A free Jekyll theme for download</description>
<link>http://pcanella.github.io/</link>
<atom:link href="http://pcanella.github.io/feed.xml" rel="self" type="application/rss+xml"/>
<pubDate>Sun, 07 Jul 2019 14:38:25 -0700</pubDate>
<lastBuildDate>Sun, 07 Jul 2019 14:38:25 -0700</lastBuildDate>
<generator>Jekyll v3.6.3</generator>
<item>
<title>Resizing a XIB Interface using Swift, the dynamic way!</title>
<description><p>Right now I’m kind of teaching myself Swift and iOS programming because:</p>
<ul>
<li>Swift is a badass language</li>
<li>iOS coding is fun and different than the web</li>
<li>It’s fun!</li>
</ul>
<p>One of the issues I had the other day was finding a simple, easy way to programatically resize a XIB file (specifically for a custom keyboard I am working on). I searched high and low on stackoverflow and Google, but to no avail. I kept thinking “OKAY someone has to know how to do this or has done this.”</p>
<p>So I found this simple example using <code>UITextField</code> and tried to apply it to my XIB view. AND IT WORKED GREAT.</p>
<p>So I’ll guide you through how to do this in Swift. This tutorial requires a basic understanding of XCode and the Storyboard features.</p>
<h2 id="prerequisite-knowledge">PREREQUISITE KNOWLEDGE</h2>
<ul>
<li>Swift syntax/semantics</li>
<li>Storyboard</li>
<li>ViewController</li>
<li>ViewController Button binding</li>
</ul>
<h2 id="step-one-hooking-up-the-viewcontroller-with-its-xib">STEP ONE: Hooking up the ViewController with it’s XIB</h2>
<p>You’ll want to create a regular old “View” in XCode. Once that is done, choose <code>Add File</code> from the <em>File</em> menu.</p>
<p>Then you’ll want to click on your XIB in the Storyboard editor and click on the “File’s Owner” object/cube. Finally, go over to the File Owner’s Identity Inspector and change it’s class to <em>YourViewController</em> (whatever you named it). Cool!</p>
<p>In your <code>ViewController</code> we want to make sure we have a reference to our XIB. So we’ll want to add something like this:</p>
<pre><code> var myXibView: UIView!
</code></pre>
<p>Our XIB is connected to our ViewController file. Let’s move on.</p>
<h2 id="step-two-changing-attributes-of-the-view">STEP TWO: Changing Attributes of the View.</h2>
<p>Once the <code>Viewcontroller</code> class is hooked up with the XIB’s <code>File's Owner</code> object, head on over to the Attributes Inspector and change the following settings in the dropdown menus (<code>Size</code> is the most important here):</p>
<ul>
<li><code>Size - Freeform</code></li>
<li><code>Orientation - Inferred</code></li>
<li><code>Status Bar - None</code></li>
<li><code>Top Bar - None</code></li>
<li><code>Bottom Bar - Inferred</code></li>
</ul>
<p>Got that? Awesome. So <code>Freeform</code> is important to allow changing the size of the layout.</p>
<h2 id="step-two-adding-a-simple-button-to-trigger-the-resize">STEP TWO: Adding a simple button to trigger the resize</h2>
<p>Next, let’s go ahead and add a button to the view. For this example, it doesn’t have to be fancy at all. Then, bind the button to your <code>ViewController</code> with an <code>@IBAction</code> func. For example, here is mine:</p>
<pre><code> @IBAction func onExpandoClick(sender: AnyObject) {
self.resizeXib(); // or any other custom method here
}
</code></pre>
<h2 id="step-three-the-resize-function">STEP THREE: The resize function!</h2>
<p>Finally, we will create a simple function to resize your XIB.</p>
<pre><code> func resizeXib(){
var testRect: CGRect = self.myXibView.frame
testRect.size.height = 400;
self.myXibView.frame = testRect;
}
</code></pre>
<h2 id="done">DONE!</h2>
<p>That’s all there is to it; on your button click the XIB will resize to 400! Obviously there are a lot of customizations you can make here including animations, etc. But there you go! If you have any questions, feel free to reach out patrickcanella at gmail dot com!</p>
</description>
<pubDate>Wed, 18 May 2016 00:00:00 -0700</pubDate>
<link>http://pcanella.github.io/blog/2016/swift-resize-xib/</link>
<guid isPermaLink="true">http://pcanella.github.io/blog/2016/swift-resize-xib/</guid>
</item>
<item>
<title>Pure CSS transition snippet</title>
<description><p>Just a quick tutorial here for those who may need it:</p>
<p>I came across an issue where I was removing a child element within multiple child elements and wanted the parent to “smoothly” readjust its height by sliding up. After trying to add different animations for the parent, I decided to play around on JSFiddle and create some solution for this thing…which actually has nothing to do with the parent at all!</p>
<p>First, let’s look at the basic HTML here</p>
<p>###HTML</p>
<pre><code class="language-html">&lt;div class="parent"&gt;
&lt;div class="child1"&gt;
Child 1
&lt;/div&gt;
&lt;div class="child2"&gt;
Child 2
&lt;/div&gt;
&lt;div class="child3"&gt;
Child 3
&lt;/div&gt;
&lt;/div&gt;
&lt;button class="test"&gt;
Remove Child 2
&lt;/button&gt;
&lt;/button&gt;
</code></pre>
<p>Basically we have a parent and child relationship. This can be divs, lis, spans, whatever, it shouldn’t really matter.</p>
<p>Then, we have some fairly simple CSS here; bear in mind for this demo/tutorial I decided to go with some static children/parents, but this also works dynamically, as long as you apply the proper styles.</p>
<p>For this demo, we are only going to remove the 2nd child, to show the demo.</p>
<p>###CSS</p>
<pre><code class="language-css">.parent{
border:1px solid red;
height:auto;
}
.child2{
transition: all 0.4s ease-in-out;
max-height:1em;
opacity:1;
}
</code></pre>
<p>As you can see, the <code>.parent</code> class is pretty straightforward. The <code>.child2</code> class has an “all” transition with an <a href="https://developers.google.com/web/fundamentals/design-and-ui/animations/the-basics-of-easing?hl=en">ease-in-out</a>. It also has the <code>max-height</code> property, which is set to 1em (aka the height of the text). This <code>max-height</code> is actually important and the basis for the actual transition itself.</p>
<p>###JavaScript</p>
<pre><code class="language-javascript">var btn = document.querySelector('.test');
btn.addEventListener('click', removeEvent, false);
function removeEvent(){
var thisChild = document.querySelector('.child2');
thisChild.style.opacity = 0;
thisChild.style['max-height'] = 0;
}
</code></pre>
<p>Pretty straightforward: we are adding an Event listener to the button so that when it’s clicked, we call <code>removeEvent</code>.</p>
<p>Inside <code>removeEvent()</code> we see that we are:</p>
<ul>
<li>Setting <code>.child2</code> to <code>thisChild</code> variable</li>
<li>adding styles of <code>opacity</code> (for the fancy fade) and <code>max-height</code> (for fancy “slide” animation</li>
</ul>
<p>That’s it! When you remove <code>.child2</code> the element will disappear (it won’t disappear completely from the DOM just yet).</p>
<p>##COOL, BUT CAN’T WE GET RID OF THE DOM NODE TOO?</p>
<p>Yes! Absolutely. JS has a built in event called <code>transitionend</code> that will fire after the CSS transition is over. Kind of a callback for CSS; nice!</p>
<p>So if we want to add a “remove DOM node” feature, we can do that as well. We’ll add a <code>transitionend</code> event listener and create a function that removes the DOM node. So in the JS, we’ll do something like this:</p>
<pre><code class="language-javascript">document.querySelector('.child2').addEventListener('transitionend', destroyDOMNode, false);
function destroyDOMNode(el){
el.target.parentNode.removeChild(e.target);
}
</code></pre>
<p>A simple one line function and we are done!</p>
<p><a href="https://jsfiddle.net/jb6pv45k/4/">Check out the final JSFiddle here</a></p>
<h2 id="but-patrick-cant-we-just-use-jquery-for-this-instead">BUT PATRICK, CAN’T WE JUST USE JQUERY FOR THIS INSTEAD?</h2>
<p>Well yeah, you could. Personally, I prefer Vanilla JavaScript though and I’ll tell you a few reasons why:</p>
<ul>
<li>Performance: CSS transitions are generally faster with animation… <a href="https://css-tricks.com/myth-busting-css-animations-vs-javascript/">well…sorta</a>. The key here is <em>simple</em> animations like this are. More complex, GPU intensive animations may not be.</li>
<li>Simpler code: Although jQuery certainly comes with a lot of animation options, it’s often cumbersome to keep up with and to get everything <em>just</em> right. CSS transitions are as easy as using <code>transitionend</code> events and adding/removing classes with the CSS <code>transition</code> property.</li>
<li>It’s definitely the future: As IE9 support wanes, CSS <code>transition</code> is becoming a browser default (YESSS) and it just makes more sense to use CSS as intended rather than constantly use JS animations.</li>
</ul>
<p>Although these are not hard and fast rules (big surprise in web dev, right?), they’re good guidelines to follow. I’m sure dozens of people will tell me I’m wrong and know nothing, but I’m somewhat experienced in both JS and CSS animations, so bring it on ;).</p>
</description>
<pubDate>Tue, 12 Apr 2016 00:00:00 -0700</pubDate>
<link>http://pcanella.github.io/blog/2016/smooth-child-transition/</link>
<guid isPermaLink="true">http://pcanella.github.io/blog/2016/smooth-child-transition/</guid>
</item>
<item>
<title>Simple Service Workers; Or why the hell does everyone keep talking about these things??</title>
<description><div style="text-align:center; margin-bottom:30px;">
<a href="https://github.com/pcanella/service-worker-sample">Yeah yeah, article, shmarticle... just show me the code!</a>
</div>
<p><em>“Oh service workers this, service workers that, offline mode will end native apps!”</em></p>
<p><strong>Have you heard this before</strong>? If you’re a Javascript developer and haven’t been living under a rock for the past 6-12 months, I bet you have too. I remember hearing about Service Workers and just assumed they were the be-all-end-all for client side JS.</p>
<p>After a bit of research (and implementation!), I kind of got a feel for what they are (albeit on a very basic level, I haven’t really done anything advanced with them) and figured out what is needed to use them! In this post, I’ll teach you how to use service workers on a simple site like patcanella.com. It’s actually super straightforward when you know what the specifics are. Anyway, let’s a take a quick step back and discuss what Service Workers are (in ELI5 mode) and what the implications are, on a very basic level.</p>
<p><strong>Service Workers, Service Workers, Service Workers!</strong></p>
<p>Like I said before, we constantly hear this term. But the question is: what are they? Why are they useful to us and how can I understand it without getting confused with loads of code being thrown at me every which way?</p>
<p>Okay, let’s tackle this one question at a time.</p>
<p><strong>What are service workers?</strong></p>
<p>A service worker is simply another thread the browser opens and uses in order to cache files and act sort of like a “proxy” to your fully loaded website. Sort of similar to <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers">Web Workers</a>, Service Workers can cache files (specified by the developer) for offline access and allow a more customized cached experience of your page or web application. Additionally, service workers allow the web to have a sophisticated Push API (which we will not touch upon here) as well as background sync APIs (also not touched upon here). For the purposes of this blog post, we will only focus on the caching API.</p>
<p>(By the way, for a more in-depth post, check out <a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">MDN’s Service Worker article</a> ; it’s really good and primarily where I learned all of this).</p>
<p>Additionally, service workers are new and changing. <a href="http://caniuse.com/#feat=serviceworkers">Check out which browsers you can support before going hog-wild with it</a>.</p>
<p>One more thing, if you want to play around in Chrome and enable it in dev tools, check out the <a href="https://www.chromium.org/blink/serviceworker/service-worker-faq">Chromium documentation</a></p>
<p>Finally, if you’d like to enable them in individual browsers, here’s how to do it:
(Thanks to <a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">MDN for this</a>):</p>
<ul>
<li>Firefox Nightly: Go to about:config and set dom.serviceWorkers.enabled to true; restart browser.</li>
<li>Chrome Canary: Go to chrome://flags and turn on experimental-web-platform-features; restart browser (note that some features are now enabled by default in Chrome.)</li>
<li>Opera: Go to opera://flags and enable Support for ServiceWorker; restart browser.</li>
</ul>
<p><strong>Okay, so they cache things. Why is this useful to me on my personal website or web application?</strong></p>
<p>Good question! You know how the browser caches a lot of CSS, images and JavaScript already, right? Well, Service Workers give us the option to heavily customize this, allowing us to cache images, scripts, files and even whole websites (!!!) on the user’s local browser. This allows us to access the site offline (as long as you accessed it online first!), which is really, really cool. Basically, this opens the door to having websites and apps act as if they were native apps!</p>
<p>This means that, for websites that don’t necessarily need network access (like a simple calculator site or some app that doesn’t require a network connection, for whatever reason), you can still view the site, click on things, etc. It’s a limited use case, sure, but super useful and a much, much better user experience than the Chrome “page cannot be found” dinosaur <a href="http://www.omgchrome.com/chrome-dinosaur-game-pterodactyl-upgrade/">which, coincidentally turns into a game</a>.</p>
<table class="image">
<caption align="bottom" style="font-size:14px">Sorry little guy, I love &amp; hate you.</caption>
<tr><td style="border:0; text-align:center;"><img src="http://i.imgur.com/FwbDS1A.png" alt="Sorry little guy, I love &amp; hate you." /></td></tr>
</table>
<p><strong>Okay, I’m still with you… so how do I make one of these things for my own website???</strong></p>
<p>Again, awesome question! It’s actually not too…too… difficult. I’ll admit I struggled a bit with it just because of so many conflicting tutorials online and ever-changing documentation. As aforementioned, MDN’s docs are arguably the best on Service Workers.</p>
<p>Here’s how you do it!</p>
<p>Okay, let’s take a simple website such as <a href="https://github.com/pcanella/service-worker-sample">this example repo</a>.</p>
<p>The folder structure is as follows:</p>
<ul>
<li>index.html (our main file)</li>
<li>page_script.js (our main file’s javascript file)</li>
<li>service_workers.js (our service worker file with the cool fancy caching logic!)</li>
<li>style.css (just a simple CSS file to show how caching works w/ service workers)</li>
</ul>
<p>IMPORTANT NOTE: Although you can run this just fine on http://localhost:80 (or whatever port), service workers WILL NOT WORK on the web unless your site is HTTPS enabled. Somewhat related: <a href="https://letsencrypt.org">letsencrypt.org</a> is an awesome place to get an SSL certificate….</p>
<p>ONE MORE NOTE: Be sure to run this on an HTTP server with localhost:8080 or something like that. You can’t use use file://, it must be over HTTP protocol. Not sure what to use? check out <a href="https://www.npmjs.com/package/http-server">http-server</a></p>
<p>We have the above file structure, cool. Now we want to really dig into the code. We won’t worry about the HTML file since it’s pretty boilerplate, but important to note that we include our JS as such:</p>
<pre><code class="language-HTML">&lt;script src="page_script.js"&gt;&lt;/script&gt;
&lt;script src="service_worker.js"&gt;&lt;/script&gt;
</code></pre>
<p>and our HTML with loaded images as:</p>
<pre><code class="language-HTML">&lt;img class="set1" src="images/set1.jpg"/&gt;
&lt;img class="set2" src="images/set2.jpg"/&gt;
&lt;img class="set3" src="images/set3.jpg"/&gt;
</code></pre>
<p>Bare bones. We don’t need anything more. Let’s keep it simple so we can understand this shit and don’t get confused!</p>
<p>If you clone <a href="https://github.com/pcanella/service-worker-sample">the repo</a> and then access the page, it’s just going to look like this (nothing fancy, right?):</p>
<p><img src="http://i.imgur.com/eWdxZkt.png" alt="simple site" /></p>
<p>Then, our CSS file just contains a simple <code>body{background-color:red;}</code> and that’s it. We just want to show that we can store all of this.</p>
<p>Let’s get to the gritty part, the Javascript. We’ll take a look at the <code>page_script.js</code> file first. Follow along in the comments, as I explain everything there :).</p>
<pre><code class="language-javascript">
// This file will get all the image tags on the page and
// just add a click handler to each. This is again, mainly
// just to show the caching mechanism in Service Workers
//
var images = document.getElementsByTagName('img');
for (var i = 0; i &lt; images.length; i++) {
//do something to each div like
images[i].addEventListener('click', setAlert);
}
function setAlert() {
alert('awesome lego set!');
}
// --------
// Okay, cool, now let's focus on the SW itself
// --------
// We want to check to see if the browser actually
// supports the serviceWorker property!
// Not sure if it does or not?
// Check out http://caniuse.com/#feat=serviceworkers
if ('serviceWorker' in navigator) {
// We want to register the service worker file with
// the browser
navigator.serviceWorker.register('service_worker.js', {
// Just the file scope; since this is in the main
// directory, we'll leave it blank. This is kind of
// a finicky option, FYI.
scope: ''
}).then(function(reg) {
// registration worked, hurray!
console.log('Registration succeeded. Scope is ' + reg.scope);
if (reg.installing) {
console.log('Service worker installing');
} else if (reg.waiting) {
console.log('Service worker installed');
} else if (reg.active) {
console.log('Service worker active');
}
}).catch(function(error) {
// registration failed. No worries, just make sure
// HTTPS is enabled and you're calling the SW
// correctly.
console.log('Registration failed with ' + error);
});
}
</code></pre>
<p>So far, so good right? In the beginning we have a simple piece of JS that allows you to trigger an alert when you click on an image. That’s all it does.</p>
<p>Then, in the service worker initialization code, we have a check to make sure the browser supports it. The <code>register</code> function is a promise (you can tell by it’s connecting <code>then()</code> function!), so after we initialize the service worker (in this case <code>service_worker.js</code> using <code>register</code> we will run the code inside of <code>then()</code> which are just console.logs to confirm or deny that it worked.</p>
<p>The last portion <code>catch(function(error){...})</code> simply alerts us if the Service Worker’s registration failed or not. If it DID fail, then nothing was installed into the browser. If that happens, don’t worry, just try again in localhost or if you’re editing directly on your own server, make sure HTTPS is enabled. Additionally, make sure you’re pointing to the right Service Worker file, especially if you’re using scope (as it is finicky and I chose not to use it on purpose).</p>
<p>Still with me? Awesome! The second part gets a little convoluted, so stay with me and make sure to read the comments.</p>
<pre><code class="language-javascript">
// Here we add an event listener for the "install" event.
// Once it registers successfully, it will automatically
// install the service worker for you. Cool!
this.addEventListener('install', function(event) {
console.log('installing....');
// Here we are once again using promises! the event
// object has a waitUntil property that is a promise.
// This promise waits until the cache portions
// (below) are populated before declaring the service
// worker "installed!"
event.waitUntil(
// See this 'v1' here? That's the version of your
// Service Worker cache. If you ever need to add
// new dependencies in the future, you'll have to
// use the "delete" functionality (more on that
// down below) and make this a 'v2'
// (or whatever you wish to call it.)
caches.open('v1').then(function(cache) {
return cache.addAll([
// These are the files we want to cache so
// we can access offline! For your project
// you'll need to add your own. You can
// include any file you wish here.
'index.html',
'page_script.js',
'style.css',
'index.html',
'/images/set1.jpg',
'/images/set2.jpg',
'/images/set3.jpg'
]);
});
);
});
// This is where the really cool stuff happens. We make use
// of the Fetch API in order to first check the cached
// resources, then if those don't exist, we check the
// server, if we are online. Essentially, this is great for
// both offline mode as well as from a site speed
// standpoint!
this.addEventListener('fetch', function(event) {
// Full documentation for respondWith is available on
// MDN (http://mzl.la/1SKtV92), but basically with this
// you are able to customize the response from the
// request you initially get by the browser.
event.respondWith(
caches.open('v1').then(function(cache) {
// caches.open look familiar? It should! We just used
// it in the code above! Here we are finding a match
// for the event.request in our cached v1 storage (in
// the browser).
//
return cache.match(event.request).then(function(response) {
// If we find a match for the request in the cache
// storage, that means our service worker will serve
// that file right up from the browser itself rather
// than going alllll the way to the server to get it! NICE!!!
// However, if the resource isn't found, then it
// WILL go ALLLL the way to the server to grab it,
// or if it's in offline mode, will break and not
// show the file. Bummer!
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
// An event listener for the 'activate' functionality that
// goes along with Service Worker registration.
this.addEventListener('activate', function activator(event) {
console.log('activate!');
// Here we see another wait until....
event.waitUntil(
// I won't go too much into detail here because
// there's a lot of stuff you can look up yourself
// (filter() and map() being two of them), but
// basically this function is in case there's
// previously cached content, then we get rid of
// it and populate it with the newest cached
// content. This is only if you need them to
// install a v2, v3, v4, etc... In a nutshell it
// wipes out their previous cache and replaces it
// with the new version.
caches.keys().then(function(keys) {
return Promise.all(keys
.filter(function(key) {
return key.indexOf('v1') !== 0;
})
.map(function(key) {
return caches.delete(key);
})
);
})
);
});
</code></pre>
<p>PHEW. That was a lot. More comments than anything though, which is good! What did we just do? In a nutshell we:</p>
<ul>
<li>Wrote some arbitrary JS that shows we can cache files (alert code)</li>
<li>Registered our first service worker in the browser with service_worker.js</li>
<li>Waited until proper installation of the service worker, then picked files to (pre)-cache using the Cache API</li>
<li>Then we took a look at the “fetch” event listener which coincides with the new Fetch API (which goes hand-in-hand with Service Workers API) and modified the response to check if we had any of the cached files in our cached storage.</li>
<li>Added a function to delete old caches if necessary (in case you’re updating the cache) and re-populate with new cache data. Nice.</li>
</ul>
<p>Now, if you decide to clone the repo I provided, run it once in the browser (on localhost) and then turn off your wifi, it should work and look the exact same, complete with click functionality!</p>
<p>That is a very simple and basic implementation of Service Workers. Again, if you want to try this on your own, <a href="https://github.com/pcanella/service-worker-sample">clone this repo</a> and fire up a simple http server (running on localhost!). If you’d like to know feel free to tweet me <a href="http://twitter.com/pcanella">@pcanella</a>!</p>
</description>
<pubDate>Sat, 12 Dec 2015 00:00:00 -0800</pubDate>
<link>http://pcanella.github.io/blog/2015/service-workers/</link>
<guid isPermaLink="true">http://pcanella.github.io/blog/2015/service-workers/</guid>
</item>
<item>
<title>The Vimeo API; Or: Why postMessage rocks!</title>
<description><p>I’m going to try to keep this post short and sweet; because:
A) It’s a quick overview
B) Nobody reads the “fluff” of coding articles (because we’re usually looking for answers!)</p>
<p>Anyway, this post is to highlight the <a href="https://developer.vimeo.com/player/js-api">Vimeo JS API</a>, it’s optional <a href="https://github.com/vimeo/player-api/tree/master/javascript">Froogaloop helper library</a> (which I actually did NOT use) and creating a quick wrapper dedicated to Vimeo’s basic API functionality.</p>
<p>For this project, we needed to use both the YouTube and Vimeo APIs to take control of their iframes. The weird thing is, both of these companies decided to implement their API quite differently.</p>
<p>If you’re debating whether or not to use Vimeo or YouTube, I would actually suggest Vimeo, only because their API is a lot more straightforward (in my opinion) and it’s easier to get up and running with it. YouTube’s iframe API is sort of clunky and you have to hack a bit to get it working how you want. You also MUST include their JS, which is actually really irritating if you want multiple instances.</p>
<p>ANYWAY, let’s get on with it.</p>
<p>Now, Vimeo’s iframe API revolves around the really cool (and fairly recent) postMessage API that allows us to send events to a 3rd party iframe where they have their own event listeners! A really cool (and secure) way to execute cross-domain requests. We can actually set this up quite easily with Vimeo’s API!</p>
<p>First, you’ll want to make sure that your embedded url looks something like this:</p>
<pre><code>&lt;iframe id="iframe_video" src="https://player.vimeo.com/video/&lt;VIDEO_ID&gt;?byline=0&amp;portrait=0&amp;title=0&amp;autoplay=0&amp;badge=0&amp;api=1&amp;player_id=iframe_video"/&gt;
</code></pre>
<p>I have some fancy parameters here (which are optional <a href="https://developer.vimeo.com/player/embedding#universal-parameters">and can be found here</a>), but the most important ones are <strong>api=1</strong> (which enables the postMessage/JS API) and the <strong>player_id</strong> (which says “ok, I’ll correspond with the iframe with ID of “iframe_video”)</p>
<p>Let’s take a look at a quick code sample (as a full reference, here’s the <a href="https://github.com/pcanella/pcanella.github.io/blob/master/_codesnippets/vimeo_wrapper.js">wrapper I have created</a>):</p>
<pre><code> post: function(action, value) {
var data = {
method: action
},
$player = document.getElementById('iframe_video');
// Just as a check to make sure value exists
if (value) {
data.value = value;
}
var url = $player.src,
message = JSON.stringify(data);
$player.contentWindow.postMessage(message, url);
}
</code></pre>
<p>Ok, so there’s a bit we should go over.</p>
<p>params:</p>
<p>-<strong>action</strong> (required): the action you want Vimeo API to execute. <a href="https://developer.vimeo.com/player/js-api#events">Need a list? Here you go</a>!</p>
<p>-<strong>value</strong> (optional depending on action): The value that is attributed to the action (for example, the action would be “seek” and the value would be a JSON object like:</p>
<pre><code>{
'seconds:'192.622',
"percent":'0.527',
"duration":'365.507'
}
</code></pre>
<p>(BTW this is totally taken from the API docs)</p>
<p>Anyway, this is all fairly straight forward if you’ve used postMessage. Haven’t used postMessage? Check out <a href="http://davidwalsh.name/demo/window-post-message.php">David Walsh’s example</a>!</p>
<p>Below is a quick demo of Vimeo’s postMessage API working in action :) (want to see the code behind it? <a href="http://jsfiddle.net/rahurrty/3/">Check out the jsFiddle</a>)</p>
<div class="iframewrapper"></div>
<p><button class="play">Play Video</button>
<button class="pause">Pause Video</button></p>
<script type="text/javascript">
var wrapper = document.querySelector('.iframewrapper');
wrapper.innerHTML = '<iframe class="test_video" id="iframe_video2" src="https://player.vimeo.com/video/113778752?byline=0&portrait=0&title=0&autoplay=0&badge=0&api=1&player_id=iframe_video2" />';
window.addEventListener('load', function(){
var play = document.querySelector('.play'),
pause = document.querySelector('.pause'),
$player = document.getElementById('iframe_video2');
play.addEventListener('click', function () {
// You don't HAVE to JSON.stringify the message itself, but sometimes postMessage is finicky with older browsers
$player.contentWindow.postMessage({
'method': 'play'
}, $player.src);
});
pause.addEventListener('click', function () {
$player.contentWindow.postMessage({
'method': 'pause'
}, $player.src);
});
});
</script>
</description>
<pubDate>Wed, 07 Oct 2015 00:00:00 -0700</pubDate>
<link>http://pcanella.github.io/blog/2015/test/</link>
<guid isPermaLink="true">http://pcanella.github.io/blog/2015/test/</guid>
</item>
</channel>
</rss>