danwrong-evil 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,2 +1,3 @@
1
+ v0.1.2 Barebones but useable
1
2
  v0.1.1 It's damn close to being useful!
2
3
  v0.1 Initial release
data/Manifest CHANGED
@@ -15,9 +15,11 @@ lib/evil/models/whitelist.rb
15
15
  lib/evil/models.rb
16
16
  lib/evil/open_id.rb
17
17
  lib/evil/plugin/base.rb
18
+ lib/evil/plugin/block_tag.rb
18
19
  lib/evil/plugin/configuration.rb
19
20
  lib/evil/plugin/environment.rb
20
21
  lib/evil/plugin/filesystem.rb
22
+ lib/evil/plugin/singleton_tag.rb
21
23
  lib/evil/plugin/tag.rb
22
24
  lib/evil/plugin.rb
23
25
  lib/evil/setup/db_tool.rb
@@ -28,10 +30,18 @@ LICENSE
28
30
  Manifest
29
31
  Rakefile
30
32
  README.textile
31
- test/app/evil_test.rb
33
+ test/application/frontend_test.rb
34
+ test/application/openid_test.rb
35
+ test/application/plugin_config_test.rb
36
+ test/application/template_test.rb
32
37
  test/dev_env.rb
33
38
  test/test_helper.rb
39
+ test/units/models/template_test.rb
40
+ test/units/models/whitelist_test.rb
34
41
  test/units/plugin/base_test.rb
42
+ test/units/plugin/configuration_test.rb
43
+ test/units/plugin/environment_test.rb
44
+ test/units/plugin/filesystem_test.rb
35
45
  test/units/plugin/tag_test.rb
36
46
  views/_banner.haml
37
47
  views/_errors.haml
data/README.textile CHANGED
@@ -2,19 +2,57 @@ h1. EVIL
2
2
 
3
3
  Author: Dan Webb (dan@danwebb.net)
4
4
 
5
- Evil is going to be a quick and easy tool for bringing together data from all over the web into a cunning little website. It's going to be easy to set up, easy to extend with plugins using any web API and be a good citzen in the Ruby web dev world by being a standard Rack app that you can deploy with Passenger, on Heroku or whatever you feel like. Hopefully it'll be mountable as part of a Rails or Merb app.
5
+ Evil is a tool for very easily putting together sites that take advantage of data from around the web. Grab your blog entries from an ATOM or RSS feed, your recent links from Delicious, your projects from Github or whatever. If it's got an API you can use pull it in to Evil and twist it together with other data and make a site. Evil does all the frustrating stuff like caching template processing and handling HTTP requests to APIs.
6
6
 
7
- To create an Evil site:
7
+ NB. It's 'working' at the moment and has decent test coverage but it's still very bare bones so it's probably not worth using until it approaches 1.0.
8
8
 
9
- <pre><code>sudo gem install evil
9
+ Here's an overview of how to use it:
10
10
 
11
- evil init {your_app_root}
12
- evil whitelist {your_openid}</pre></code>
11
+ 1. Install the gem
13
12
 
14
- Then point Passenger at it, send it up to Heruko or run it on your grandad's ZX Spectrum then go to /admin and get going.
13
+ @sudo gem install danwrong-evil@
15
14
 
16
- h2. Planned features
15
+ 2. Generate a site skeleton
17
16
 
18
- * Caching via Rack::Cache
19
- * Plugin architecture that makes it easy to interact with web APIs (probably based on HTTParty)
20
- * Simple OpenID whitelist for access to the admin interface
17
+ @evil init {path}@
18
+
19
+ This will give you the files and dirs that you need for your site including a public directory to add static files to if you need them.
20
+
21
+ 3. Whitelist your OpenID
22
+
23
+ <code><pre>cd {path}
24
+ evil whitelist {your OpenID URL}</pre></code>
25
+
26
+ You can use wildcards in here if you want so if you wanted to let in all subdomains of danwebb.net you could do *.danwebb.net.
27
+
28
+ 4. Upload the whole directory to your server and point passenger at it. Something like this in your Apache config should do it:
29
+
30
+ <code><pre><VirtualHost *:80>
31
+ ServerName www.example.com
32
+ DocumentRoot "/var/www/example/public"
33
+ </VirtualHost></pre></code>
34
+
35
+ 5. Go to the admin site and start writing templates. It will be at /admin. Just log in with your OpenID.
36
+
37
+ 6. Mess around. Create templates using liquid syntax, give them routes using the Sinatra/Rails syntax eg. /mythings/:id.
38
+
39
+ That's all for now. More detail later.
40
+
41
+ h2. Acknowledgements
42
+
43
+ Evil is built, as all good software is, on the efforts of lots of brilliant projects:
44
+
45
+ * Sinatra
46
+ * Rack::Cache
47
+ * Liquid
48
+ * HTTParty
49
+ * jQuery
50
+ * HAML
51
+
52
+ So thanks to all the authors.
53
+
54
+ h2. In the works...
55
+
56
+ There will be a suite of built in plugins covering all of the popular services and protocols (Flickr, Twitter, ATOM/RSS, Github, Upcoming, Delicious, YQL, Last.fm + loads more). Also, I'll be adding documentation to write your own plugins and easy handling of OAuth. This is just the very start.
57
+
58
+ Feedback welcome.
data/Rakefile CHANGED
@@ -13,7 +13,8 @@ Echoe.new("evil") do |p|
13
13
 
14
14
  p.development_dependencies = ['shoulda']
15
15
  p.retain_gemspec = true
16
- p.ignore_pattern = ['test/example/**/*']
16
+ p.ignore_pattern = ['test/example/**/*', 'test/evil.db']
17
+ p.rcov_options = "--exclude 'gems/*'"
17
18
  end
18
19
 
19
20
  desc 'Move assets from text/example to assets'
data/assets/evil-lib.js CHANGED
@@ -213,10 +213,309 @@
213
213
  }
214
214
  });
215
215
 
216
- $.ajaxSetup({
217
- beforeSend: function(xhr) {
218
- xhr.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
219
- }
220
- });
221
-
222
- })(jQuery);
216
+ })(jQuery);
217
+
218
+ jQuery.tableDnD = {
219
+ /** Keep hold of the current table being dragged */
220
+ currentTable : null,
221
+ /** Keep hold of the current drag object if any */
222
+ dragObject: null,
223
+ /** The current mouse offset */
224
+ mouseOffset: null,
225
+ /** Remember the old value of Y so that we don't do too much processing */
226
+ oldY: 0,
227
+
228
+ /** Actually build the structure */
229
+ build: function(options) {
230
+ // Set up the defaults if any
231
+
232
+ this.each(function() {
233
+ // This is bound to each matching table, set up the defaults and override with user options
234
+ this.tableDnDConfig = jQuery.extend({
235
+ onDragStyle: null,
236
+ onDropStyle: null,
237
+ // Add in the default class for whileDragging
238
+ onDragClass: "tDnD_whileDrag",
239
+ onDrop: null,
240
+ onDragStart: null,
241
+ scrollAmount: 5,
242
+ serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
243
+ serializeParamName: null, // If you want to specify another parameter name instead of the table ID
244
+ dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable
245
+ }, options || {});
246
+ // Now make the rows draggable
247
+ jQuery.tableDnD.makeDraggable(this);
248
+ });
249
+
250
+ // Now we need to capture the mouse up and mouse move event
251
+ // We can use bind so that we don't interfere with other event handlers
252
+ jQuery(document)
253
+ .bind('mousemove', jQuery.tableDnD.mousemove)
254
+ .bind('mouseup', jQuery.tableDnD.mouseup);
255
+
256
+ // Don't break the chain
257
+ return this;
258
+ },
259
+
260
+ /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
261
+ makeDraggable: function(table) {
262
+ var config = table.tableDnDConfig;
263
+ if (table.tableDnDConfig.dragHandle) {
264
+ // We only need to add the event to the specified cells
265
+ var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table);
266
+ cells.each(function() {
267
+ // The cell is bound to "this"
268
+ jQuery(this).mousedown(function(ev) {
269
+ jQuery.tableDnD.dragObject = this.parentNode;
270
+ jQuery.tableDnD.currentTable = table;
271
+ jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
272
+ if (config.onDragStart) {
273
+ // Call the onDrop method if there is one
274
+ config.onDragStart(table, this);
275
+ }
276
+ return false;
277
+ });
278
+ })
279
+ } else {
280
+ // For backwards compatibility, we add the event to the whole row
281
+ var rows = jQuery("tr", table); // get all the rows as a wrapped set
282
+ rows.each(function() {
283
+ // Iterate through each row, the row is bound to "this"
284
+ var row = jQuery(this);
285
+ if (! row.hasClass("nodrag")) {
286
+ row.mousedown(function(ev) {
287
+ if (ev.target.tagName == "TD") {
288
+ jQuery.tableDnD.dragObject = this;
289
+ jQuery.tableDnD.currentTable = table;
290
+ jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
291
+ if (config.onDragStart) {
292
+ // Call the onDrop method if there is one
293
+ config.onDragStart(table, this);
294
+ }
295
+ return false;
296
+ }
297
+ }).css("cursor", "move"); // Store the tableDnD object
298
+ }
299
+ });
300
+ }
301
+ },
302
+
303
+ updateTables: function() {
304
+ this.each(function() {
305
+ // this is now bound to each matching table
306
+ if (this.tableDnDConfig) {
307
+ jQuery.tableDnD.makeDraggable(this);
308
+ }
309
+ })
310
+ },
311
+
312
+ /** Get the mouse coordinates from the event (allowing for browser differences) */
313
+ mouseCoords: function(ev){
314
+ if(ev.pageX || ev.pageY){
315
+ return {x:ev.pageX, y:ev.pageY};
316
+ }
317
+ return {
318
+ x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
319
+ y:ev.clientY + document.body.scrollTop - document.body.clientTop
320
+ };
321
+ },
322
+
323
+ /** Given a target element and a mouse event, get the mouse offset from that element.
324
+ To do this we need the element's position and the mouse position */
325
+ getMouseOffset: function(target, ev) {
326
+ ev = ev || window.event;
327
+
328
+ var docPos = this.getPosition(target);
329
+ var mousePos = this.mouseCoords(ev);
330
+ return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
331
+ },
332
+
333
+ /** Get the position of an element by going up the DOM tree and adding up all the offsets */
334
+ getPosition: function(e){
335
+ var left = 0;
336
+ var top = 0;
337
+ /** Safari fix -- thanks to Luis Chato for this! */
338
+ if (e.offsetHeight == 0) {
339
+ /** Safari 2 doesn't correctly grab the offsetTop of a table row
340
+ this is detailed here:
341
+ http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
342
+ the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
343
+ note that firefox will return a text node as a first child, so designing a more thorough
344
+ solution may need to take that into account, for now this seems to work in firefox, safari, ie */
345
+ e = e.firstChild; // a table cell
346
+ }
347
+
348
+ while (e.offsetParent){
349
+ left += e.offsetLeft;
350
+ top += e.offsetTop;
351
+ e = e.offsetParent;
352
+ }
353
+
354
+ left += e.offsetLeft;
355
+ top += e.offsetTop;
356
+
357
+ return {x:left, y:top};
358
+ },
359
+
360
+ mousemove: function(ev) {
361
+ if (jQuery.tableDnD.dragObject == null) {
362
+ return;
363
+ }
364
+
365
+ var dragObj = jQuery(jQuery.tableDnD.dragObject);
366
+ var config = jQuery.tableDnD.currentTable.tableDnDConfig;
367
+ var mousePos = jQuery.tableDnD.mouseCoords(ev);
368
+ var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;
369
+ //auto scroll the window
370
+ var yOffset = window.pageYOffset;
371
+ if (document.all) {
372
+ // Windows version
373
+ //yOffset=document.body.scrollTop;
374
+ if (typeof document.compatMode != 'undefined' &&
375
+ document.compatMode != 'BackCompat') {
376
+ yOffset = document.documentElement.scrollTop;
377
+ }
378
+ else if (typeof document.body != 'undefined') {
379
+ yOffset=document.body.scrollTop;
380
+ }
381
+
382
+ }
383
+
384
+ if (mousePos.y-yOffset < config.scrollAmount) {
385
+ window.scrollBy(0, -config.scrollAmount);
386
+ } else {
387
+ var windowHeight = window.innerHeight ? window.innerHeight
388
+ : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
389
+ if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) {
390
+ window.scrollBy(0, config.scrollAmount);
391
+ }
392
+ }
393
+
394
+
395
+ if (y != jQuery.tableDnD.oldY) {
396
+ // work out if we're going up or down...
397
+ var movingDown = y > jQuery.tableDnD.oldY;
398
+ // update the old value
399
+ jQuery.tableDnD.oldY = y;
400
+ // update the style to show we're dragging
401
+ if (config.onDragClass) {
402
+ dragObj.addClass(config.onDragClass);
403
+ } else {
404
+ dragObj.css(config.onDragStyle);
405
+ }
406
+ // If we're over a row then move the dragged row to there so that the user sees the
407
+ // effect dynamically
408
+ var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y);
409
+ if (currentRow) {
410
+ // TODO worry about what happens when there are multiple TBODIES
411
+ if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
412
+ jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
413
+ } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
414
+ jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
415
+ }
416
+ }
417
+ }
418
+
419
+ return false;
420
+ },
421
+
422
+ /** We're only worried about the y position really, because we can only move rows up and down */
423
+ findDropTargetRow: function(draggedRow, y) {
424
+ var rows = jQuery.tableDnD.currentTable.rows;
425
+ for (var i=0; i<rows.length; i++) {
426
+ var row = rows[i];
427
+ var rowY = this.getPosition(row).y;
428
+ var rowHeight = parseInt(row.offsetHeight)/2;
429
+ if (row.offsetHeight == 0) {
430
+ rowY = this.getPosition(row.firstChild).y;
431
+ rowHeight = parseInt(row.firstChild.offsetHeight)/2;
432
+ }
433
+ // Because we always have to insert before, we need to offset the height a bit
434
+ if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
435
+ // that's the row we're over
436
+ // If it's the same as the current row, ignore it
437
+ if (row == draggedRow) {return null;}
438
+ var config = jQuery.tableDnD.currentTable.tableDnDConfig;
439
+ if (config.onAllowDrop) {
440
+ if (config.onAllowDrop(draggedRow, row)) {
441
+ return row;
442
+ } else {
443
+ return null;
444
+ }
445
+ } else {
446
+ // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
447
+ var nodrop = jQuery(row).hasClass("nodrop");
448
+ if (! nodrop) {
449
+ return row;
450
+ } else {
451
+ return null;
452
+ }
453
+ }
454
+ return row;
455
+ }
456
+ }
457
+ return null;
458
+ },
459
+
460
+ mouseup: function(e) {
461
+ if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) {
462
+ var droppedRow = jQuery.tableDnD.dragObject;
463
+ var config = jQuery.tableDnD.currentTable.tableDnDConfig;
464
+ // If we have a dragObject, then we need to release it,
465
+ // The row will already have been moved to the right place so we just reset stuff
466
+ if (config.onDragClass) {
467
+ jQuery(droppedRow).removeClass(config.onDragClass);
468
+ } else {
469
+ jQuery(droppedRow).css(config.onDropStyle);
470
+ }
471
+ jQuery.tableDnD.dragObject = null;
472
+ if (config.onDrop) {
473
+ // Call the onDrop method if there is one
474
+ config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
475
+ }
476
+ jQuery.tableDnD.currentTable = null; // let go of the table too
477
+ }
478
+ },
479
+
480
+ serialize: function() {
481
+ if (jQuery.tableDnD.currentTable) {
482
+ return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
483
+ } else {
484
+ return "Error: No Table id set, you need to set an id on your table and every row";
485
+ }
486
+ },
487
+
488
+ serializeTable: function(table) {
489
+ var result = "";
490
+ var tableId = table.id;
491
+ var rows = table.rows;
492
+ for (var i=0; i<rows.length; i++) {
493
+ if (result.length > 0) result += "&";
494
+ var rowId = rows[i].id;
495
+ if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
496
+ rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
497
+ }
498
+
499
+ result += tableId + '[]=' + rowId;
500
+ }
501
+ return result;
502
+ },
503
+
504
+ serializeTables: function() {
505
+ var result = "";
506
+ this.each(function() {
507
+ // this is now bound to each matching table
508
+ result += jQuery.tableDnD.serializeTable(this);
509
+ });
510
+ return result;
511
+ }
512
+
513
+ }
514
+
515
+ jQuery.fn.extend(
516
+ {
517
+ tableDnD : jQuery.tableDnD.build,
518
+ tableDnDUpdate : jQuery.tableDnD.updateTables,
519
+ tableDnDSerialize: jQuery.tableDnD.serializeTables
520
+ }
521
+ );
data/assets/evil.css CHANGED
@@ -180,6 +180,10 @@ input.submit {
180
180
  margin: 0 2% 2em 0;
181
181
  }
182
182
 
183
+ #overview table#templates tr.dragging {
184
+ background: #444;
185
+ }
186
+
183
187
  #content form {
184
188
  width: 50%;
185
189
  margin: 0 auto;
@@ -193,12 +197,16 @@ form p {
193
197
  margin: 1em 0;
194
198
  }
195
199
 
196
- form input.text, form textarea {
200
+ form input.text, form textarea, form input.short {
197
201
  width: 100%;
198
202
  font-family: Verdana, Helvetica, Arial, sans-serif;
199
203
  font-size: 1em;
200
204
  }
201
205
 
206
+ form input.short {
207
+ width: 30%;
208
+ }
209
+
202
210
  form div.errors {
203
211
  border: 1px solid red;
204
212
  font-size: 0.8em;