scrivito_sdk 1.0.0 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/README.md +1 -1
  4. data/app/controllers/scrivito/legacy_redirect_controller.rb +11 -0
  5. data/app/controllers/scrivito/objs_controller.rb +15 -5
  6. data/app/controllers/scrivito/webservice_controller.rb +4 -3
  7. data/app/controllers/scrivito/workspaces_controller.rb +24 -29
  8. data/app/helpers/scrivito_helper.rb +82 -37
  9. data/app/views/scrivito/objs/binary_no_cache.json.jbuilder +1 -0
  10. data/app/views/scrivito/objs/search.json.jbuilder +5 -5
  11. data/app/views/scrivito/webservice/error.json.jbuilder +2 -2
  12. data/config/ca-bundle.crt +1 -1
  13. data/config/precedence_routes.rb +51 -48
  14. data/config/routes.rb +1 -14
  15. data/lib/assets/javascripts/scrivito_ui.js +2447 -266
  16. data/lib/assets/stylesheets/scrivito.css +1 -1
  17. data/lib/assets/stylesheets/scrivito_ui.css +1 -1
  18. data/lib/generators/scrivito/install/install_generator.rb +12 -0
  19. data/lib/generators/scrivito/install/templates/config/initializers/scrivito.rb +3 -0
  20. data/lib/scrivito/attribute_definition.rb +13 -1
  21. data/lib/scrivito/attribute_deserializer.rb +4 -4
  22. data/lib/scrivito/attribute_value_renderer.rb +79 -0
  23. data/lib/scrivito/backend/obj_data_cache.rb +15 -15
  24. data/lib/scrivito/backend/obj_data_from_rest.rb +1 -21
  25. data/lib/scrivito/backend/obj_query.rb +2 -2
  26. data/lib/scrivito/basic_obj.rb +17 -6
  27. data/lib/scrivito/binary.rb +13 -5
  28. data/lib/scrivito/cache/chainable.rb +10 -5
  29. data/lib/scrivito/cache/file_store.rb +4 -0
  30. data/lib/scrivito/cache/ram_store.rb +4 -0
  31. data/lib/scrivito/child_list_tag.rb +16 -14
  32. data/lib/scrivito/client_error.rb +10 -0
  33. data/lib/scrivito/cms_backend.rb +66 -291
  34. data/lib/scrivito/cms_data_cache.rb +7 -9
  35. data/lib/scrivito/cms_dispatch_controller.rb +1 -10
  36. data/lib/scrivito/cms_field_tag.rb +2 -1
  37. data/lib/scrivito/cms_rest_api.rb +2 -0
  38. data/lib/scrivito/cms_routing.rb +26 -22
  39. data/lib/scrivito/configuration.rb +38 -0
  40. data/lib/scrivito/connection_manager.rb +69 -0
  41. data/lib/scrivito/controller_actions.rb +2 -2
  42. data/lib/scrivito/controller_helper.rb +2 -2
  43. data/lib/scrivito/date_attribute.rb +4 -1
  44. data/lib/scrivito/deprecation.rb +5 -4
  45. data/lib/scrivito/editing_context.rb +2 -2
  46. data/lib/scrivito/errors.rb +17 -0
  47. data/lib/scrivito/image_tag.rb +2 -2
  48. data/lib/scrivito/link_parser.rb +10 -5
  49. data/lib/scrivito/meta_data_collection.rb +11 -0
  50. data/lib/scrivito/obj_collection.rb +1 -1
  51. data/lib/scrivito/obj_facet_value.rb +19 -7
  52. data/lib/scrivito/obj_params_parser.rb +43 -14
  53. data/lib/scrivito/obj_search_builder.rb +1 -2
  54. data/lib/scrivito/obj_search_enumerator/batch.rb +22 -0
  55. data/lib/scrivito/obj_search_enumerator/batch_iterator.rb +36 -0
  56. data/lib/scrivito/obj_search_enumerator/query_executor.rb +35 -0
  57. data/lib/scrivito/obj_search_enumerator.rb +218 -93
  58. data/lib/scrivito/obj_update_params_parser.rb +1 -0
  59. data/lib/scrivito/preset_routes.rb +25 -0
  60. data/lib/scrivito/revision.rb +13 -11
  61. data/lib/scrivito/route.rb +62 -0
  62. data/lib/scrivito/routing_extensions.rb +92 -0
  63. data/lib/scrivito/sdk_engine.rb +4 -0
  64. data/lib/scrivito/task.rb +77 -0
  65. data/lib/scrivito/type_computer.rb +3 -3
  66. data/lib/scrivito/ui_config.rb +4 -0
  67. data/lib/scrivito/user.rb +24 -18
  68. data/lib/scrivito/workspace/publish_checker.rb +2 -3
  69. data/lib/scrivito/workspace.rb +38 -6
  70. data/lib/scrivito/workspace_data.rb +0 -14
  71. metadata +14 -10
  72. data/lib/scrivito/content_service.rb +0 -121
  73. data/lib/scrivito/content_state.rb +0 -109
  74. data/lib/scrivito/content_state_caching.rb +0 -47
  75. data/lib/scrivito/content_state_visitor.rb +0 -19
  76. data/lib/scrivito/obj_data_from_service.rb +0 -63
  77. data/lib/scrivito/workspace_data_from_service.rb +0 -43
@@ -11170,6 +11170,1316 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
11170
11170
 
11171
11171
  return $.widget;
11172
11172
 
11173
+ }));
11174
+ /*! jQuery UI - v1.11.4 - 2015-08-21
11175
+ * http://jqueryui.com
11176
+ * Includes: effect.js
11177
+ * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
11178
+
11179
+
11180
+ (function( factory ) {
11181
+ if ( typeof define === "function" && define.amd ) {
11182
+
11183
+ // AMD. Register as an anonymous module.
11184
+ define([ "jquery" ], factory );
11185
+ } else {
11186
+
11187
+ // Browser globals
11188
+ factory( jQuery );
11189
+ }
11190
+ }(function( $ ) {
11191
+ /*!
11192
+ * jQuery UI Effects 1.11.4
11193
+ * http://jqueryui.com
11194
+ *
11195
+ * Copyright jQuery Foundation and other contributors
11196
+ * Released under the MIT license.
11197
+ * http://jquery.org/license
11198
+ *
11199
+ * http://api.jqueryui.com/category/effects-core/
11200
+ */
11201
+
11202
+
11203
+ var dataSpace = "ui-effects-",
11204
+
11205
+ // Create a local jQuery because jQuery Color relies on it and the
11206
+ // global may not exist with AMD and a custom build (#10199)
11207
+ jQuery = $;
11208
+
11209
+ $.effects = {
11210
+ effect: {}
11211
+ };
11212
+
11213
+ /*!
11214
+ * jQuery Color Animations v2.1.2
11215
+ * https://github.com/jquery/jquery-color
11216
+ *
11217
+ * Copyright 2014 jQuery Foundation and other contributors
11218
+ * Released under the MIT license.
11219
+ * http://jquery.org/license
11220
+ *
11221
+ * Date: Wed Jan 16 08:47:09 2013 -0600
11222
+ */
11223
+ (function( jQuery, undefined ) {
11224
+
11225
+ var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
11226
+
11227
+ // plusequals test for += 100 -= 100
11228
+ rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
11229
+ // a set of RE's that can match strings and generate color tuples.
11230
+ stringParsers = [ {
11231
+ re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11232
+ parse: function( execResult ) {
11233
+ return [
11234
+ execResult[ 1 ],
11235
+ execResult[ 2 ],
11236
+ execResult[ 3 ],
11237
+ execResult[ 4 ]
11238
+ ];
11239
+ }
11240
+ }, {
11241
+ re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11242
+ parse: function( execResult ) {
11243
+ return [
11244
+ execResult[ 1 ] * 2.55,
11245
+ execResult[ 2 ] * 2.55,
11246
+ execResult[ 3 ] * 2.55,
11247
+ execResult[ 4 ]
11248
+ ];
11249
+ }
11250
+ }, {
11251
+ // this regex ignores A-F because it's compared against an already lowercased string
11252
+ re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
11253
+ parse: function( execResult ) {
11254
+ return [
11255
+ parseInt( execResult[ 1 ], 16 ),
11256
+ parseInt( execResult[ 2 ], 16 ),
11257
+ parseInt( execResult[ 3 ], 16 )
11258
+ ];
11259
+ }
11260
+ }, {
11261
+ // this regex ignores A-F because it's compared against an already lowercased string
11262
+ re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
11263
+ parse: function( execResult ) {
11264
+ return [
11265
+ parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
11266
+ parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
11267
+ parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
11268
+ ];
11269
+ }
11270
+ }, {
11271
+ re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11272
+ space: "hsla",
11273
+ parse: function( execResult ) {
11274
+ return [
11275
+ execResult[ 1 ],
11276
+ execResult[ 2 ] / 100,
11277
+ execResult[ 3 ] / 100,
11278
+ execResult[ 4 ]
11279
+ ];
11280
+ }
11281
+ } ],
11282
+
11283
+ // jQuery.Color( )
11284
+ color = jQuery.Color = function( color, green, blue, alpha ) {
11285
+ return new jQuery.Color.fn.parse( color, green, blue, alpha );
11286
+ },
11287
+ spaces = {
11288
+ rgba: {
11289
+ props: {
11290
+ red: {
11291
+ idx: 0,
11292
+ type: "byte"
11293
+ },
11294
+ green: {
11295
+ idx: 1,
11296
+ type: "byte"
11297
+ },
11298
+ blue: {
11299
+ idx: 2,
11300
+ type: "byte"
11301
+ }
11302
+ }
11303
+ },
11304
+
11305
+ hsla: {
11306
+ props: {
11307
+ hue: {
11308
+ idx: 0,
11309
+ type: "degrees"
11310
+ },
11311
+ saturation: {
11312
+ idx: 1,
11313
+ type: "percent"
11314
+ },
11315
+ lightness: {
11316
+ idx: 2,
11317
+ type: "percent"
11318
+ }
11319
+ }
11320
+ }
11321
+ },
11322
+ propTypes = {
11323
+ "byte": {
11324
+ floor: true,
11325
+ max: 255
11326
+ },
11327
+ "percent": {
11328
+ max: 1
11329
+ },
11330
+ "degrees": {
11331
+ mod: 360,
11332
+ floor: true
11333
+ }
11334
+ },
11335
+ support = color.support = {},
11336
+
11337
+ // element for support tests
11338
+ supportElem = jQuery( "<p>" )[ 0 ],
11339
+
11340
+ // colors = jQuery.Color.names
11341
+ colors,
11342
+
11343
+ // local aliases of functions called often
11344
+ each = jQuery.each;
11345
+
11346
+ // determine rgba support immediately
11347
+ supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
11348
+ support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
11349
+
11350
+ // define cache name and alpha properties
11351
+ // for rgba and hsla spaces
11352
+ each( spaces, function( spaceName, space ) {
11353
+ space.cache = "_" + spaceName;
11354
+ space.props.alpha = {
11355
+ idx: 3,
11356
+ type: "percent",
11357
+ def: 1
11358
+ };
11359
+ });
11360
+
11361
+ function clamp( value, prop, allowEmpty ) {
11362
+ var type = propTypes[ prop.type ] || {};
11363
+
11364
+ if ( value == null ) {
11365
+ return (allowEmpty || !prop.def) ? null : prop.def;
11366
+ }
11367
+
11368
+ // ~~ is an short way of doing floor for positive numbers
11369
+ value = type.floor ? ~~value : parseFloat( value );
11370
+
11371
+ // IE will pass in empty strings as value for alpha,
11372
+ // which will hit this case
11373
+ if ( isNaN( value ) ) {
11374
+ return prop.def;
11375
+ }
11376
+
11377
+ if ( type.mod ) {
11378
+ // we add mod before modding to make sure that negatives values
11379
+ // get converted properly: -10 -> 350
11380
+ return (value + type.mod) % type.mod;
11381
+ }
11382
+
11383
+ // for now all property types without mod have min and max
11384
+ return 0 > value ? 0 : type.max < value ? type.max : value;
11385
+ }
11386
+
11387
+ function stringParse( string ) {
11388
+ var inst = color(),
11389
+ rgba = inst._rgba = [];
11390
+
11391
+ string = string.toLowerCase();
11392
+
11393
+ each( stringParsers, function( i, parser ) {
11394
+ var parsed,
11395
+ match = parser.re.exec( string ),
11396
+ values = match && parser.parse( match ),
11397
+ spaceName = parser.space || "rgba";
11398
+
11399
+ if ( values ) {
11400
+ parsed = inst[ spaceName ]( values );
11401
+
11402
+ // if this was an rgba parse the assignment might happen twice
11403
+ // oh well....
11404
+ inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
11405
+ rgba = inst._rgba = parsed._rgba;
11406
+
11407
+ // exit each( stringParsers ) here because we matched
11408
+ return false;
11409
+ }
11410
+ });
11411
+
11412
+ // Found a stringParser that handled it
11413
+ if ( rgba.length ) {
11414
+
11415
+ // if this came from a parsed string, force "transparent" when alpha is 0
11416
+ // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
11417
+ if ( rgba.join() === "0,0,0,0" ) {
11418
+ jQuery.extend( rgba, colors.transparent );
11419
+ }
11420
+ return inst;
11421
+ }
11422
+
11423
+ // named colors
11424
+ return colors[ string ];
11425
+ }
11426
+
11427
+ color.fn = jQuery.extend( color.prototype, {
11428
+ parse: function( red, green, blue, alpha ) {
11429
+ if ( red === undefined ) {
11430
+ this._rgba = [ null, null, null, null ];
11431
+ return this;
11432
+ }
11433
+ if ( red.jquery || red.nodeType ) {
11434
+ red = jQuery( red ).css( green );
11435
+ green = undefined;
11436
+ }
11437
+
11438
+ var inst = this,
11439
+ type = jQuery.type( red ),
11440
+ rgba = this._rgba = [];
11441
+
11442
+ // more than 1 argument specified - assume ( red, green, blue, alpha )
11443
+ if ( green !== undefined ) {
11444
+ red = [ red, green, blue, alpha ];
11445
+ type = "array";
11446
+ }
11447
+
11448
+ if ( type === "string" ) {
11449
+ return this.parse( stringParse( red ) || colors._default );
11450
+ }
11451
+
11452
+ if ( type === "array" ) {
11453
+ each( spaces.rgba.props, function( key, prop ) {
11454
+ rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
11455
+ });
11456
+ return this;
11457
+ }
11458
+
11459
+ if ( type === "object" ) {
11460
+ if ( red instanceof color ) {
11461
+ each( spaces, function( spaceName, space ) {
11462
+ if ( red[ space.cache ] ) {
11463
+ inst[ space.cache ] = red[ space.cache ].slice();
11464
+ }
11465
+ });
11466
+ } else {
11467
+ each( spaces, function( spaceName, space ) {
11468
+ var cache = space.cache;
11469
+ each( space.props, function( key, prop ) {
11470
+
11471
+ // if the cache doesn't exist, and we know how to convert
11472
+ if ( !inst[ cache ] && space.to ) {
11473
+
11474
+ // if the value was null, we don't need to copy it
11475
+ // if the key was alpha, we don't need to copy it either
11476
+ if ( key === "alpha" || red[ key ] == null ) {
11477
+ return;
11478
+ }
11479
+ inst[ cache ] = space.to( inst._rgba );
11480
+ }
11481
+
11482
+ // this is the only case where we allow nulls for ALL properties.
11483
+ // call clamp with alwaysAllowEmpty
11484
+ inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
11485
+ });
11486
+
11487
+ // everything defined but alpha?
11488
+ if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
11489
+ // use the default of 1
11490
+ inst[ cache ][ 3 ] = 1;
11491
+ if ( space.from ) {
11492
+ inst._rgba = space.from( inst[ cache ] );
11493
+ }
11494
+ }
11495
+ });
11496
+ }
11497
+ return this;
11498
+ }
11499
+ },
11500
+ is: function( compare ) {
11501
+ var is = color( compare ),
11502
+ same = true,
11503
+ inst = this;
11504
+
11505
+ each( spaces, function( _, space ) {
11506
+ var localCache,
11507
+ isCache = is[ space.cache ];
11508
+ if (isCache) {
11509
+ localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
11510
+ each( space.props, function( _, prop ) {
11511
+ if ( isCache[ prop.idx ] != null ) {
11512
+ same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
11513
+ return same;
11514
+ }
11515
+ });
11516
+ }
11517
+ return same;
11518
+ });
11519
+ return same;
11520
+ },
11521
+ _space: function() {
11522
+ var used = [],
11523
+ inst = this;
11524
+ each( spaces, function( spaceName, space ) {
11525
+ if ( inst[ space.cache ] ) {
11526
+ used.push( spaceName );
11527
+ }
11528
+ });
11529
+ return used.pop();
11530
+ },
11531
+ transition: function( other, distance ) {
11532
+ var end = color( other ),
11533
+ spaceName = end._space(),
11534
+ space = spaces[ spaceName ],
11535
+ startColor = this.alpha() === 0 ? color( "transparent" ) : this,
11536
+ start = startColor[ space.cache ] || space.to( startColor._rgba ),
11537
+ result = start.slice();
11538
+
11539
+ end = end[ space.cache ];
11540
+ each( space.props, function( key, prop ) {
11541
+ var index = prop.idx,
11542
+ startValue = start[ index ],
11543
+ endValue = end[ index ],
11544
+ type = propTypes[ prop.type ] || {};
11545
+
11546
+ // if null, don't override start value
11547
+ if ( endValue === null ) {
11548
+ return;
11549
+ }
11550
+ // if null - use end
11551
+ if ( startValue === null ) {
11552
+ result[ index ] = endValue;
11553
+ } else {
11554
+ if ( type.mod ) {
11555
+ if ( endValue - startValue > type.mod / 2 ) {
11556
+ startValue += type.mod;
11557
+ } else if ( startValue - endValue > type.mod / 2 ) {
11558
+ startValue -= type.mod;
11559
+ }
11560
+ }
11561
+ result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
11562
+ }
11563
+ });
11564
+ return this[ spaceName ]( result );
11565
+ },
11566
+ blend: function( opaque ) {
11567
+ // if we are already opaque - return ourself
11568
+ if ( this._rgba[ 3 ] === 1 ) {
11569
+ return this;
11570
+ }
11571
+
11572
+ var rgb = this._rgba.slice(),
11573
+ a = rgb.pop(),
11574
+ blend = color( opaque )._rgba;
11575
+
11576
+ return color( jQuery.map( rgb, function( v, i ) {
11577
+ return ( 1 - a ) * blend[ i ] + a * v;
11578
+ }));
11579
+ },
11580
+ toRgbaString: function() {
11581
+ var prefix = "rgba(",
11582
+ rgba = jQuery.map( this._rgba, function( v, i ) {
11583
+ return v == null ? ( i > 2 ? 1 : 0 ) : v;
11584
+ });
11585
+
11586
+ if ( rgba[ 3 ] === 1 ) {
11587
+ rgba.pop();
11588
+ prefix = "rgb(";
11589
+ }
11590
+
11591
+ return prefix + rgba.join() + ")";
11592
+ },
11593
+ toHslaString: function() {
11594
+ var prefix = "hsla(",
11595
+ hsla = jQuery.map( this.hsla(), function( v, i ) {
11596
+ if ( v == null ) {
11597
+ v = i > 2 ? 1 : 0;
11598
+ }
11599
+
11600
+ // catch 1 and 2
11601
+ if ( i && i < 3 ) {
11602
+ v = Math.round( v * 100 ) + "%";
11603
+ }
11604
+ return v;
11605
+ });
11606
+
11607
+ if ( hsla[ 3 ] === 1 ) {
11608
+ hsla.pop();
11609
+ prefix = "hsl(";
11610
+ }
11611
+ return prefix + hsla.join() + ")";
11612
+ },
11613
+ toHexString: function( includeAlpha ) {
11614
+ var rgba = this._rgba.slice(),
11615
+ alpha = rgba.pop();
11616
+
11617
+ if ( includeAlpha ) {
11618
+ rgba.push( ~~( alpha * 255 ) );
11619
+ }
11620
+
11621
+ return "#" + jQuery.map( rgba, function( v ) {
11622
+
11623
+ // default to 0 when nulls exist
11624
+ v = ( v || 0 ).toString( 16 );
11625
+ return v.length === 1 ? "0" + v : v;
11626
+ }).join("");
11627
+ },
11628
+ toString: function() {
11629
+ return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
11630
+ }
11631
+ });
11632
+ color.fn.parse.prototype = color.fn;
11633
+
11634
+ // hsla conversions adapted from:
11635
+ // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
11636
+
11637
+ function hue2rgb( p, q, h ) {
11638
+ h = ( h + 1 ) % 1;
11639
+ if ( h * 6 < 1 ) {
11640
+ return p + ( q - p ) * h * 6;
11641
+ }
11642
+ if ( h * 2 < 1) {
11643
+ return q;
11644
+ }
11645
+ if ( h * 3 < 2 ) {
11646
+ return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
11647
+ }
11648
+ return p;
11649
+ }
11650
+
11651
+ spaces.hsla.to = function( rgba ) {
11652
+ if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
11653
+ return [ null, null, null, rgba[ 3 ] ];
11654
+ }
11655
+ var r = rgba[ 0 ] / 255,
11656
+ g = rgba[ 1 ] / 255,
11657
+ b = rgba[ 2 ] / 255,
11658
+ a = rgba[ 3 ],
11659
+ max = Math.max( r, g, b ),
11660
+ min = Math.min( r, g, b ),
11661
+ diff = max - min,
11662
+ add = max + min,
11663
+ l = add * 0.5,
11664
+ h, s;
11665
+
11666
+ if ( min === max ) {
11667
+ h = 0;
11668
+ } else if ( r === max ) {
11669
+ h = ( 60 * ( g - b ) / diff ) + 360;
11670
+ } else if ( g === max ) {
11671
+ h = ( 60 * ( b - r ) / diff ) + 120;
11672
+ } else {
11673
+ h = ( 60 * ( r - g ) / diff ) + 240;
11674
+ }
11675
+
11676
+ // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
11677
+ // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
11678
+ if ( diff === 0 ) {
11679
+ s = 0;
11680
+ } else if ( l <= 0.5 ) {
11681
+ s = diff / add;
11682
+ } else {
11683
+ s = diff / ( 2 - add );
11684
+ }
11685
+ return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
11686
+ };
11687
+
11688
+ spaces.hsla.from = function( hsla ) {
11689
+ if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
11690
+ return [ null, null, null, hsla[ 3 ] ];
11691
+ }
11692
+ var h = hsla[ 0 ] / 360,
11693
+ s = hsla[ 1 ],
11694
+ l = hsla[ 2 ],
11695
+ a = hsla[ 3 ],
11696
+ q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
11697
+ p = 2 * l - q;
11698
+
11699
+ return [
11700
+ Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
11701
+ Math.round( hue2rgb( p, q, h ) * 255 ),
11702
+ Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
11703
+ a
11704
+ ];
11705
+ };
11706
+
11707
+ each( spaces, function( spaceName, space ) {
11708
+ var props = space.props,
11709
+ cache = space.cache,
11710
+ to = space.to,
11711
+ from = space.from;
11712
+
11713
+ // makes rgba() and hsla()
11714
+ color.fn[ spaceName ] = function( value ) {
11715
+
11716
+ // generate a cache for this space if it doesn't exist
11717
+ if ( to && !this[ cache ] ) {
11718
+ this[ cache ] = to( this._rgba );
11719
+ }
11720
+ if ( value === undefined ) {
11721
+ return this[ cache ].slice();
11722
+ }
11723
+
11724
+ var ret,
11725
+ type = jQuery.type( value ),
11726
+ arr = ( type === "array" || type === "object" ) ? value : arguments,
11727
+ local = this[ cache ].slice();
11728
+
11729
+ each( props, function( key, prop ) {
11730
+ var val = arr[ type === "object" ? key : prop.idx ];
11731
+ if ( val == null ) {
11732
+ val = local[ prop.idx ];
11733
+ }
11734
+ local[ prop.idx ] = clamp( val, prop );
11735
+ });
11736
+
11737
+ if ( from ) {
11738
+ ret = color( from( local ) );
11739
+ ret[ cache ] = local;
11740
+ return ret;
11741
+ } else {
11742
+ return color( local );
11743
+ }
11744
+ };
11745
+
11746
+ // makes red() green() blue() alpha() hue() saturation() lightness()
11747
+ each( props, function( key, prop ) {
11748
+ // alpha is included in more than one space
11749
+ if ( color.fn[ key ] ) {
11750
+ return;
11751
+ }
11752
+ color.fn[ key ] = function( value ) {
11753
+ var vtype = jQuery.type( value ),
11754
+ fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
11755
+ local = this[ fn ](),
11756
+ cur = local[ prop.idx ],
11757
+ match;
11758
+
11759
+ if ( vtype === "undefined" ) {
11760
+ return cur;
11761
+ }
11762
+
11763
+ if ( vtype === "function" ) {
11764
+ value = value.call( this, cur );
11765
+ vtype = jQuery.type( value );
11766
+ }
11767
+ if ( value == null && prop.empty ) {
11768
+ return this;
11769
+ }
11770
+ if ( vtype === "string" ) {
11771
+ match = rplusequals.exec( value );
11772
+ if ( match ) {
11773
+ value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
11774
+ }
11775
+ }
11776
+ local[ prop.idx ] = value;
11777
+ return this[ fn ]( local );
11778
+ };
11779
+ });
11780
+ });
11781
+
11782
+ // add cssHook and .fx.step function for each named hook.
11783
+ // accept a space separated string of properties
11784
+ color.hook = function( hook ) {
11785
+ var hooks = hook.split( " " );
11786
+ each( hooks, function( i, hook ) {
11787
+ jQuery.cssHooks[ hook ] = {
11788
+ set: function( elem, value ) {
11789
+ var parsed, curElem,
11790
+ backgroundColor = "";
11791
+
11792
+ if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
11793
+ value = color( parsed || value );
11794
+ if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
11795
+ curElem = hook === "backgroundColor" ? elem.parentNode : elem;
11796
+ while (
11797
+ (backgroundColor === "" || backgroundColor === "transparent") &&
11798
+ curElem && curElem.style
11799
+ ) {
11800
+ try {
11801
+ backgroundColor = jQuery.css( curElem, "backgroundColor" );
11802
+ curElem = curElem.parentNode;
11803
+ } catch ( e ) {
11804
+ }
11805
+ }
11806
+
11807
+ value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
11808
+ backgroundColor :
11809
+ "_default" );
11810
+ }
11811
+
11812
+ value = value.toRgbaString();
11813
+ }
11814
+ try {
11815
+ elem.style[ hook ] = value;
11816
+ } catch ( e ) {
11817
+ // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
11818
+ }
11819
+ }
11820
+ };
11821
+ jQuery.fx.step[ hook ] = function( fx ) {
11822
+ if ( !fx.colorInit ) {
11823
+ fx.start = color( fx.elem, hook );
11824
+ fx.end = color( fx.end );
11825
+ fx.colorInit = true;
11826
+ }
11827
+ jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
11828
+ };
11829
+ });
11830
+
11831
+ };
11832
+
11833
+ color.hook( stepHooks );
11834
+
11835
+ jQuery.cssHooks.borderColor = {
11836
+ expand: function( value ) {
11837
+ var expanded = {};
11838
+
11839
+ each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
11840
+ expanded[ "border" + part + "Color" ] = value;
11841
+ });
11842
+ return expanded;
11843
+ }
11844
+ };
11845
+
11846
+ // Basic color names only.
11847
+ // Usage of any of the other color names requires adding yourself or including
11848
+ // jquery.color.svg-names.js.
11849
+ colors = jQuery.Color.names = {
11850
+ // 4.1. Basic color keywords
11851
+ aqua: "#00ffff",
11852
+ black: "#000000",
11853
+ blue: "#0000ff",
11854
+ fuchsia: "#ff00ff",
11855
+ gray: "#808080",
11856
+ green: "#008000",
11857
+ lime: "#00ff00",
11858
+ maroon: "#800000",
11859
+ navy: "#000080",
11860
+ olive: "#808000",
11861
+ purple: "#800080",
11862
+ red: "#ff0000",
11863
+ silver: "#c0c0c0",
11864
+ teal: "#008080",
11865
+ white: "#ffffff",
11866
+ yellow: "#ffff00",
11867
+
11868
+ // 4.2.3. "transparent" color keyword
11869
+ transparent: [ null, null, null, 0 ],
11870
+
11871
+ _default: "#ffffff"
11872
+ };
11873
+
11874
+ })( jQuery );
11875
+
11876
+ /******************************************************************************/
11877
+ /****************************** CLASS ANIMATIONS ******************************/
11878
+ /******************************************************************************/
11879
+ (function() {
11880
+
11881
+ var classAnimationActions = [ "add", "remove", "toggle" ],
11882
+ shorthandStyles = {
11883
+ border: 1,
11884
+ borderBottom: 1,
11885
+ borderColor: 1,
11886
+ borderLeft: 1,
11887
+ borderRight: 1,
11888
+ borderTop: 1,
11889
+ borderWidth: 1,
11890
+ margin: 1,
11891
+ padding: 1
11892
+ };
11893
+
11894
+ $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
11895
+ $.fx.step[ prop ] = function( fx ) {
11896
+ if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
11897
+ jQuery.style( fx.elem, prop, fx.end );
11898
+ fx.setAttr = true;
11899
+ }
11900
+ };
11901
+ });
11902
+
11903
+ function getElementStyles( elem ) {
11904
+ var key, len,
11905
+ style = elem.ownerDocument.defaultView ?
11906
+ elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
11907
+ elem.currentStyle,
11908
+ styles = {};
11909
+
11910
+ if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
11911
+ len = style.length;
11912
+ while ( len-- ) {
11913
+ key = style[ len ];
11914
+ if ( typeof style[ key ] === "string" ) {
11915
+ styles[ $.camelCase( key ) ] = style[ key ];
11916
+ }
11917
+ }
11918
+ // support: Opera, IE <9
11919
+ } else {
11920
+ for ( key in style ) {
11921
+ if ( typeof style[ key ] === "string" ) {
11922
+ styles[ key ] = style[ key ];
11923
+ }
11924
+ }
11925
+ }
11926
+
11927
+ return styles;
11928
+ }
11929
+
11930
+ function styleDifference( oldStyle, newStyle ) {
11931
+ var diff = {},
11932
+ name, value;
11933
+
11934
+ for ( name in newStyle ) {
11935
+ value = newStyle[ name ];
11936
+ if ( oldStyle[ name ] !== value ) {
11937
+ if ( !shorthandStyles[ name ] ) {
11938
+ if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
11939
+ diff[ name ] = value;
11940
+ }
11941
+ }
11942
+ }
11943
+ }
11944
+
11945
+ return diff;
11946
+ }
11947
+
11948
+ // support: jQuery <1.8
11949
+ if ( !$.fn.addBack ) {
11950
+ $.fn.addBack = function( selector ) {
11951
+ return this.add( selector == null ?
11952
+ this.prevObject : this.prevObject.filter( selector )
11953
+ );
11954
+ };
11955
+ }
11956
+
11957
+ $.effects.animateClass = function( value, duration, easing, callback ) {
11958
+ var o = $.speed( duration, easing, callback );
11959
+
11960
+ return this.queue( function() {
11961
+ var animated = $( this ),
11962
+ baseClass = animated.attr( "class" ) || "",
11963
+ applyClassChange,
11964
+ allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
11965
+
11966
+ // map the animated objects to store the original styles.
11967
+ allAnimations = allAnimations.map(function() {
11968
+ var el = $( this );
11969
+ return {
11970
+ el: el,
11971
+ start: getElementStyles( this )
11972
+ };
11973
+ });
11974
+
11975
+ // apply class change
11976
+ applyClassChange = function() {
11977
+ $.each( classAnimationActions, function(i, action) {
11978
+ if ( value[ action ] ) {
11979
+ animated[ action + "Class" ]( value[ action ] );
11980
+ }
11981
+ });
11982
+ };
11983
+ applyClassChange();
11984
+
11985
+ // map all animated objects again - calculate new styles and diff
11986
+ allAnimations = allAnimations.map(function() {
11987
+ this.end = getElementStyles( this.el[ 0 ] );
11988
+ this.diff = styleDifference( this.start, this.end );
11989
+ return this;
11990
+ });
11991
+
11992
+ // apply original class
11993
+ animated.attr( "class", baseClass );
11994
+
11995
+ // map all animated objects again - this time collecting a promise
11996
+ allAnimations = allAnimations.map(function() {
11997
+ var styleInfo = this,
11998
+ dfd = $.Deferred(),
11999
+ opts = $.extend({}, o, {
12000
+ queue: false,
12001
+ complete: function() {
12002
+ dfd.resolve( styleInfo );
12003
+ }
12004
+ });
12005
+
12006
+ this.el.animate( this.diff, opts );
12007
+ return dfd.promise();
12008
+ });
12009
+
12010
+ // once all animations have completed:
12011
+ $.when.apply( $, allAnimations.get() ).done(function() {
12012
+
12013
+ // set the final class
12014
+ applyClassChange();
12015
+
12016
+ // for each animated element,
12017
+ // clear all css properties that were animated
12018
+ $.each( arguments, function() {
12019
+ var el = this.el;
12020
+ $.each( this.diff, function(key) {
12021
+ el.css( key, "" );
12022
+ });
12023
+ });
12024
+
12025
+ // this is guarnteed to be there if you use jQuery.speed()
12026
+ // it also handles dequeuing the next anim...
12027
+ o.complete.call( animated[ 0 ] );
12028
+ });
12029
+ });
12030
+ };
12031
+
12032
+ $.fn.extend({
12033
+ addClass: (function( orig ) {
12034
+ return function( classNames, speed, easing, callback ) {
12035
+ return speed ?
12036
+ $.effects.animateClass.call( this,
12037
+ { add: classNames }, speed, easing, callback ) :
12038
+ orig.apply( this, arguments );
12039
+ };
12040
+ })( $.fn.addClass ),
12041
+
12042
+ removeClass: (function( orig ) {
12043
+ return function( classNames, speed, easing, callback ) {
12044
+ return arguments.length > 1 ?
12045
+ $.effects.animateClass.call( this,
12046
+ { remove: classNames }, speed, easing, callback ) :
12047
+ orig.apply( this, arguments );
12048
+ };
12049
+ })( $.fn.removeClass ),
12050
+
12051
+ toggleClass: (function( orig ) {
12052
+ return function( classNames, force, speed, easing, callback ) {
12053
+ if ( typeof force === "boolean" || force === undefined ) {
12054
+ if ( !speed ) {
12055
+ // without speed parameter
12056
+ return orig.apply( this, arguments );
12057
+ } else {
12058
+ return $.effects.animateClass.call( this,
12059
+ (force ? { add: classNames } : { remove: classNames }),
12060
+ speed, easing, callback );
12061
+ }
12062
+ } else {
12063
+ // without force parameter
12064
+ return $.effects.animateClass.call( this,
12065
+ { toggle: classNames }, force, speed, easing );
12066
+ }
12067
+ };
12068
+ })( $.fn.toggleClass ),
12069
+
12070
+ switchClass: function( remove, add, speed, easing, callback) {
12071
+ return $.effects.animateClass.call( this, {
12072
+ add: add,
12073
+ remove: remove
12074
+ }, speed, easing, callback );
12075
+ }
12076
+ });
12077
+
12078
+ })();
12079
+
12080
+ /******************************************************************************/
12081
+ /*********************************** EFFECTS **********************************/
12082
+ /******************************************************************************/
12083
+
12084
+ (function() {
12085
+
12086
+ $.extend( $.effects, {
12087
+ version: "1.11.4",
12088
+
12089
+ // Saves a set of properties in a data storage
12090
+ save: function( element, set ) {
12091
+ for ( var i = 0; i < set.length; i++ ) {
12092
+ if ( set[ i ] !== null ) {
12093
+ element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
12094
+ }
12095
+ }
12096
+ },
12097
+
12098
+ // Restores a set of previously saved properties from a data storage
12099
+ restore: function( element, set ) {
12100
+ var val, i;
12101
+ for ( i = 0; i < set.length; i++ ) {
12102
+ if ( set[ i ] !== null ) {
12103
+ val = element.data( dataSpace + set[ i ] );
12104
+ // support: jQuery 1.6.2
12105
+ // http://bugs.jquery.com/ticket/9917
12106
+ // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
12107
+ // We can't differentiate between "" and 0 here, so we just assume
12108
+ // empty string since it's likely to be a more common value...
12109
+ if ( val === undefined ) {
12110
+ val = "";
12111
+ }
12112
+ element.css( set[ i ], val );
12113
+ }
12114
+ }
12115
+ },
12116
+
12117
+ setMode: function( el, mode ) {
12118
+ if (mode === "toggle") {
12119
+ mode = el.is( ":hidden" ) ? "show" : "hide";
12120
+ }
12121
+ return mode;
12122
+ },
12123
+
12124
+ // Translates a [top,left] array into a baseline value
12125
+ // this should be a little more flexible in the future to handle a string & hash
12126
+ getBaseline: function( origin, original ) {
12127
+ var y, x;
12128
+ switch ( origin[ 0 ] ) {
12129
+ case "top": y = 0; break;
12130
+ case "middle": y = 0.5; break;
12131
+ case "bottom": y = 1; break;
12132
+ default: y = origin[ 0 ] / original.height;
12133
+ }
12134
+ switch ( origin[ 1 ] ) {
12135
+ case "left": x = 0; break;
12136
+ case "center": x = 0.5; break;
12137
+ case "right": x = 1; break;
12138
+ default: x = origin[ 1 ] / original.width;
12139
+ }
12140
+ return {
12141
+ x: x,
12142
+ y: y
12143
+ };
12144
+ },
12145
+
12146
+ // Wraps the element around a wrapper that copies position properties
12147
+ createWrapper: function( element ) {
12148
+
12149
+ // if the element is already wrapped, return it
12150
+ if ( element.parent().is( ".ui-effects-wrapper" )) {
12151
+ return element.parent();
12152
+ }
12153
+
12154
+ // wrap the element
12155
+ var props = {
12156
+ width: element.outerWidth(true),
12157
+ height: element.outerHeight(true),
12158
+ "float": element.css( "float" )
12159
+ },
12160
+ wrapper = $( "<div></div>" )
12161
+ .addClass( "ui-effects-wrapper" )
12162
+ .css({
12163
+ fontSize: "100%",
12164
+ background: "transparent",
12165
+ border: "none",
12166
+ margin: 0,
12167
+ padding: 0
12168
+ }),
12169
+ // Store the size in case width/height are defined in % - Fixes #5245
12170
+ size = {
12171
+ width: element.width(),
12172
+ height: element.height()
12173
+ },
12174
+ active = document.activeElement;
12175
+
12176
+ // support: Firefox
12177
+ // Firefox incorrectly exposes anonymous content
12178
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
12179
+ try {
12180
+ active.id;
12181
+ } catch ( e ) {
12182
+ active = document.body;
12183
+ }
12184
+
12185
+ element.wrap( wrapper );
12186
+
12187
+ // Fixes #7595 - Elements lose focus when wrapped.
12188
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
12189
+ $( active ).focus();
12190
+ }
12191
+
12192
+ wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
12193
+
12194
+ // transfer positioning properties to the wrapper
12195
+ if ( element.css( "position" ) === "static" ) {
12196
+ wrapper.css({ position: "relative" });
12197
+ element.css({ position: "relative" });
12198
+ } else {
12199
+ $.extend( props, {
12200
+ position: element.css( "position" ),
12201
+ zIndex: element.css( "z-index" )
12202
+ });
12203
+ $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
12204
+ props[ pos ] = element.css( pos );
12205
+ if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
12206
+ props[ pos ] = "auto";
12207
+ }
12208
+ });
12209
+ element.css({
12210
+ position: "relative",
12211
+ top: 0,
12212
+ left: 0,
12213
+ right: "auto",
12214
+ bottom: "auto"
12215
+ });
12216
+ }
12217
+ element.css(size);
12218
+
12219
+ return wrapper.css( props ).show();
12220
+ },
12221
+
12222
+ removeWrapper: function( element ) {
12223
+ var active = document.activeElement;
12224
+
12225
+ if ( element.parent().is( ".ui-effects-wrapper" ) ) {
12226
+ element.parent().replaceWith( element );
12227
+
12228
+ // Fixes #7595 - Elements lose focus when wrapped.
12229
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
12230
+ $( active ).focus();
12231
+ }
12232
+ }
12233
+
12234
+ return element;
12235
+ },
12236
+
12237
+ setTransition: function( element, list, factor, value ) {
12238
+ value = value || {};
12239
+ $.each( list, function( i, x ) {
12240
+ var unit = element.cssUnit( x );
12241
+ if ( unit[ 0 ] > 0 ) {
12242
+ value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
12243
+ }
12244
+ });
12245
+ return value;
12246
+ }
12247
+ });
12248
+
12249
+ // return an effect options object for the given parameters:
12250
+ function _normalizeArguments( effect, options, speed, callback ) {
12251
+
12252
+ // allow passing all options as the first parameter
12253
+ if ( $.isPlainObject( effect ) ) {
12254
+ options = effect;
12255
+ effect = effect.effect;
12256
+ }
12257
+
12258
+ // convert to an object
12259
+ effect = { effect: effect };
12260
+
12261
+ // catch (effect, null, ...)
12262
+ if ( options == null ) {
12263
+ options = {};
12264
+ }
12265
+
12266
+ // catch (effect, callback)
12267
+ if ( $.isFunction( options ) ) {
12268
+ callback = options;
12269
+ speed = null;
12270
+ options = {};
12271
+ }
12272
+
12273
+ // catch (effect, speed, ?)
12274
+ if ( typeof options === "number" || $.fx.speeds[ options ] ) {
12275
+ callback = speed;
12276
+ speed = options;
12277
+ options = {};
12278
+ }
12279
+
12280
+ // catch (effect, options, callback)
12281
+ if ( $.isFunction( speed ) ) {
12282
+ callback = speed;
12283
+ speed = null;
12284
+ }
12285
+
12286
+ // add options to effect
12287
+ if ( options ) {
12288
+ $.extend( effect, options );
12289
+ }
12290
+
12291
+ speed = speed || options.duration;
12292
+ effect.duration = $.fx.off ? 0 :
12293
+ typeof speed === "number" ? speed :
12294
+ speed in $.fx.speeds ? $.fx.speeds[ speed ] :
12295
+ $.fx.speeds._default;
12296
+
12297
+ effect.complete = callback || options.complete;
12298
+
12299
+ return effect;
12300
+ }
12301
+
12302
+ function standardAnimationOption( option ) {
12303
+ // Valid standard speeds (nothing, number, named speed)
12304
+ if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
12305
+ return true;
12306
+ }
12307
+
12308
+ // Invalid strings - treat as "normal" speed
12309
+ if ( typeof option === "string" && !$.effects.effect[ option ] ) {
12310
+ return true;
12311
+ }
12312
+
12313
+ // Complete callback
12314
+ if ( $.isFunction( option ) ) {
12315
+ return true;
12316
+ }
12317
+
12318
+ // Options hash (but not naming an effect)
12319
+ if ( typeof option === "object" && !option.effect ) {
12320
+ return true;
12321
+ }
12322
+
12323
+ // Didn't match any standard API
12324
+ return false;
12325
+ }
12326
+
12327
+ $.fn.extend({
12328
+ effect: function( /* effect, options, speed, callback */ ) {
12329
+ var args = _normalizeArguments.apply( this, arguments ),
12330
+ mode = args.mode,
12331
+ queue = args.queue,
12332
+ effectMethod = $.effects.effect[ args.effect ];
12333
+
12334
+ if ( $.fx.off || !effectMethod ) {
12335
+ // delegate to the original method (e.g., .show()) if possible
12336
+ if ( mode ) {
12337
+ return this[ mode ]( args.duration, args.complete );
12338
+ } else {
12339
+ return this.each( function() {
12340
+ if ( args.complete ) {
12341
+ args.complete.call( this );
12342
+ }
12343
+ });
12344
+ }
12345
+ }
12346
+
12347
+ function run( next ) {
12348
+ var elem = $( this ),
12349
+ complete = args.complete,
12350
+ mode = args.mode;
12351
+
12352
+ function done() {
12353
+ if ( $.isFunction( complete ) ) {
12354
+ complete.call( elem[0] );
12355
+ }
12356
+ if ( $.isFunction( next ) ) {
12357
+ next();
12358
+ }
12359
+ }
12360
+
12361
+ // If the element already has the correct final state, delegate to
12362
+ // the core methods so the internal tracking of "olddisplay" works.
12363
+ if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
12364
+ elem[ mode ]();
12365
+ done();
12366
+ } else {
12367
+ effectMethod.call( elem[0], args, done );
12368
+ }
12369
+ }
12370
+
12371
+ return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
12372
+ },
12373
+
12374
+ show: (function( orig ) {
12375
+ return function( option ) {
12376
+ if ( standardAnimationOption( option ) ) {
12377
+ return orig.apply( this, arguments );
12378
+ } else {
12379
+ var args = _normalizeArguments.apply( this, arguments );
12380
+ args.mode = "show";
12381
+ return this.effect.call( this, args );
12382
+ }
12383
+ };
12384
+ })( $.fn.show ),
12385
+
12386
+ hide: (function( orig ) {
12387
+ return function( option ) {
12388
+ if ( standardAnimationOption( option ) ) {
12389
+ return orig.apply( this, arguments );
12390
+ } else {
12391
+ var args = _normalizeArguments.apply( this, arguments );
12392
+ args.mode = "hide";
12393
+ return this.effect.call( this, args );
12394
+ }
12395
+ };
12396
+ })( $.fn.hide ),
12397
+
12398
+ toggle: (function( orig ) {
12399
+ return function( option ) {
12400
+ if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
12401
+ return orig.apply( this, arguments );
12402
+ } else {
12403
+ var args = _normalizeArguments.apply( this, arguments );
12404
+ args.mode = "toggle";
12405
+ return this.effect.call( this, args );
12406
+ }
12407
+ };
12408
+ })( $.fn.toggle ),
12409
+
12410
+ // helper functions
12411
+ cssUnit: function(key) {
12412
+ var style = this.css( key ),
12413
+ val = [];
12414
+
12415
+ $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
12416
+ if ( style.indexOf( unit ) > 0 ) {
12417
+ val = [ parseFloat( style ), unit ];
12418
+ }
12419
+ });
12420
+ return val;
12421
+ }
12422
+ });
12423
+
12424
+ })();
12425
+
12426
+ /******************************************************************************/
12427
+ /*********************************** EASING ***********************************/
12428
+ /******************************************************************************/
12429
+
12430
+ (function() {
12431
+
12432
+ // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
12433
+
12434
+ var baseEasings = {};
12435
+
12436
+ $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
12437
+ baseEasings[ name ] = function( p ) {
12438
+ return Math.pow( p, i + 2 );
12439
+ };
12440
+ });
12441
+
12442
+ $.extend( baseEasings, {
12443
+ Sine: function( p ) {
12444
+ return 1 - Math.cos( p * Math.PI / 2 );
12445
+ },
12446
+ Circ: function( p ) {
12447
+ return 1 - Math.sqrt( 1 - p * p );
12448
+ },
12449
+ Elastic: function( p ) {
12450
+ return p === 0 || p === 1 ? p :
12451
+ -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
12452
+ },
12453
+ Back: function( p ) {
12454
+ return p * p * ( 3 * p - 2 );
12455
+ },
12456
+ Bounce: function( p ) {
12457
+ var pow2,
12458
+ bounce = 4;
12459
+
12460
+ while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
12461
+ return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
12462
+ }
12463
+ });
12464
+
12465
+ $.each( baseEasings, function( name, easeIn ) {
12466
+ $.easing[ "easeIn" + name ] = easeIn;
12467
+ $.easing[ "easeOut" + name ] = function( p ) {
12468
+ return 1 - easeIn( 1 - p );
12469
+ };
12470
+ $.easing[ "easeInOut" + name ] = function( p ) {
12471
+ return p < 0.5 ?
12472
+ easeIn( p * 2 ) / 2 :
12473
+ 1 - easeIn( p * -2 + 2 ) / 2;
12474
+ };
12475
+ });
12476
+
12477
+ })();
12478
+
12479
+ var effect = $.effects;
12480
+
12481
+
12482
+
11173
12483
  }));
11174
12484
  /*!
11175
12485
  * jQuery UI Mouse 1.11.4
@@ -26722,6 +28032,62 @@ helpers = helpers || Handlebars.helpers; data = data || {};
26722
28032
  });
26723
28033
  return this.ScrivitoHandlebarsTemplates["element_overlay"];
26724
28034
  }).call(this);
28035
+ (function() {
28036
+ this.ScrivitoHandlebarsTemplates || (this.ScrivitoHandlebarsTemplates = {});
28037
+ this.ScrivitoHandlebarsTemplates["error_dialog"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
28038
+ this.compilerInfo = [3,'>= 1.0.0-rc.4'];
28039
+ helpers = helpers || Handlebars.helpers; data = data || {};
28040
+ var buffer = "", stack1, options, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, functionType="function", self=this;
28041
+
28042
+ function program1(depth0,data) {
28043
+
28044
+ var buffer = "", stack1, options;
28045
+ buffer += "\n <a class=\"scrivito_toggle_details\" href=\"#\">";
28046
+ options = {hash:{},data:data};
28047
+ buffer += escapeExpression(((stack1 = helpers.translate),stack1 ? stack1.call(depth0, "error_dialog.toggle_details", options) : helperMissing.call(depth0, "translate", "error_dialog.toggle_details", options)))
28048
+ + "</a>\n ";
28049
+ return buffer;
28050
+ }
28051
+
28052
+ function program3(depth0,data) {
28053
+
28054
+ var buffer = "", stack1, stack2, options;
28055
+ buffer += "\n <div class=\"scrivito_modal_body\" style=\"display:none\">\n <h4>";
28056
+ options = {hash:{},data:data};
28057
+ buffer += escapeExpression(((stack1 = helpers.translate),stack1 ? stack1.call(depth0, "error_dialog.error_details", options) : helperMissing.call(depth0, "translate", "error_dialog.error_details", options)))
28058
+ + ":</h4>\n ";
28059
+ stack2 = helpers.each.call(depth0, depth0.details, {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
28060
+ if(stack2 || stack2 === 0) { buffer += stack2; }
28061
+ buffer += "\n </div>\n ";
28062
+ return buffer;
28063
+ }
28064
+ function program4(depth0,data) {
28065
+
28066
+ var buffer = "";
28067
+ buffer += "\n <div>"
28068
+ + escapeExpression((typeof depth0 === functionType ? depth0.apply(depth0) : depth0))
28069
+ + "</div>\n ";
28070
+ return buffer;
28071
+ }
28072
+
28073
+ buffer += "<div class=\"scrivito_error_dialog scrivito_modal_prompt scrivito_center_dialog scrivito_yellow\">\n <div class=\"scrivito_modal_header\">\n <i class=\"scrivito_icon\">&#xf01e;</i>\n <h3 class=\"scrivito_title\">\n ";
28074
+ if (stack1 = helpers.message) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
28075
+ else { stack1 = depth0.message; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
28076
+ buffer += escapeExpression(stack1)
28077
+ + "\n ";
28078
+ stack1 = helpers['if'].call(depth0, depth0.details, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
28079
+ if(stack1 || stack1 === 0) { buffer += stack1; }
28080
+ buffer += "\n </h3>\n </div>\n\n ";
28081
+ stack1 = helpers['if'].call(depth0, depth0.details, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
28082
+ if(stack1 || stack1 === 0) { buffer += stack1; }
28083
+ buffer += "\n\n <div class=\"scrivito_modal_footer\">\n <a href=\"#\" class=\"scrivito_button scrivito_close\">";
28084
+ options = {hash:{},data:data};
28085
+ buffer += escapeExpression(((stack1 = helpers.translate),stack1 ? stack1.call(depth0, "close", options) : helperMissing.call(depth0, "translate", "close", options)))
28086
+ + "</a>\n </div>\n</div>\n";
28087
+ return buffer;
28088
+ });
28089
+ return this.ScrivitoHandlebarsTemplates["error_dialog"];
28090
+ }).call(this);
26725
28091
  (function() {
26726
28092
  this.ScrivitoHandlebarsTemplates || (this.ScrivitoHandlebarsTemplates = {});
26727
28093
  this.ScrivitoHandlebarsTemplates["iframe_dialog"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
@@ -27991,6 +29357,9 @@ $.i18n().load({
27991
29357
  'current_page_link_dialog.title': 'Diese Seite teilen',
27992
29358
  'current_page_link_dialog.description': 'Mit dieser URL können Sie die aktuelle Seite als Teil dieser Arbeitskopie teilen. Die Empfänger müssen angemeldet sein und Zugriff auf die Arbeitskopie haben.',
27993
29359
 
29360
+ 'error_dialog.toggle_details': 'Technische Details',
29361
+ 'error_dialog.error_details': 'Technische Details',
29362
+
27994
29363
  'commands.current_page_link.title': 'Diese Seite teilen',
27995
29364
  'commands.current_page_link.is_deleted': 'Eine gelöschte Seite kann nicht geteilt werden, weil sie in der Vorschau nicht zugänglich ist',
27996
29365
 
@@ -28001,11 +29370,13 @@ $.i18n().load({
28001
29370
  'commands.create_workspace.dialog.placeholder': 'Neuer Titel',
28002
29371
  'commands.create_workspace.dialog.accept': 'Anlegen',
28003
29372
 
29373
+ 'commands.rename_workspace.forbidden': 'Die Arbeitskopie kann aufgrund fehlender Benutzerrechte nicht umbenannt werden.',
28004
29374
  'commands.rename_workspace.title': 'Umbenennen',
28005
29375
  'commands.rename_workspace.dialog.title': '"$1" umbenennen',
28006
29376
  'commands.rename_workspace.dialog.description': 'Bitte geben Sie den neuen Titel der Arbeitskopie ein.',
28007
29377
  'commands.rename_workspace.dialog.accept': 'Umbenennen',
28008
29378
 
29379
+ 'commands.rebase_workspace.forbidden': 'Die Arbeitskopie kann aufgrund fehlender Benutzerrechte nicht aktualisiert werden.',
28009
29380
  'commands.rebase_workspace.title': 'Aktualisieren',
28010
29381
  'commands.rebase_workspace.tooltip': 'Arbeitskopie "$1" is veraltet. Bitte aktualisieren Sie sie.',
28011
29382
  'commands.rebase_workspace.uptodate': 'Arbeitskopie "$1" muss nicht aktualisiert werden.',
@@ -28013,11 +29384,13 @@ $.i18n().load({
28013
29384
  'commands.rebase_workspace.has_conflicts.description': 'Ihre Arbeitskopie konnte nicht vollständig aktualisiert werden. Einige Inhalte wurden auch in einer anderen Arbeitskopie geändert, die inzwischen veröffentlicht wurde. Bitte entnehmen Sie die Details der Liste der Änderungen.',
28014
29385
  'commands.rebase_workspace.open_changes_dialog': 'Änderungen anzeigen',
28015
29386
 
29387
+ 'commands.delete_workspace.forbidden': 'Die Arbeitskopie kann aufgrund fehlender Benutzerrechte nicht gelöscht werden.',
28016
29388
  'commands.delete_workspace.title': 'Löschen',
28017
29389
  'commands.delete_workspace.dialog.title': 'Wirklich "$1" löschen?',
28018
29390
  'commands.delete_workspace.dialog.description': 'Eine gelöschte Arbeitskopie kann nicht wiederhergestellt werden.',
28019
29391
  'commands.delete_workspace.dialog.confirm': 'Löschen',
28020
29392
 
29393
+ 'commands.workspace_settings.forbidden': 'Die Einstellungen der Arbeitskopie können aufgrund fehlender Benutzerrechte nicht bearbeitet werden.',
28021
29394
  'commands.workspace_settings.title': 'Einstellungen bearbeiten',
28022
29395
  'commands.workspace_settings.dialog.title': 'Einstellungen von "$1"',
28023
29396
 
@@ -28099,9 +29472,6 @@ $.i18n().load({
28099
29472
  'commands.choose_and_create_widget.disabled': 'Sie können hier keine Widgets einfügen.',
28100
29473
  'commands.create_widget.title': '$1 einfügen',
28101
29474
 
28102
- 'commands.add_content.title': 'Inhalt einfügen',
28103
- 'commands.add_content.not_allowed': 'Es ist nicht erlaubt in dieses Feld beliebige Inhalte einzufügen',
28104
-
28105
29475
  'commands.widget_details.title': 'Widget-Eigenschaften',
28106
29476
  'commands.widget_details.no_details_view': 'Dieses Widget hat keine Eigenschaften',
28107
29477
  'commands.widget_details.dialog.title': 'Eigenschaften von "$1"',
@@ -28138,12 +29508,13 @@ $.i18n().load({
28138
29508
 
28139
29509
  'ajax.error': 'Die Kommunikation mit dem CMS ist aufgrund eines Fehlers fehlgeschlagen: $1',
28140
29510
  'ajax.error.communication': 'Die Kommunikation mit dem CMS ist fehlgeschlagen. Bitte überprüfen Sie Ihre Netzwerkverbindung.',
28141
- 'ajax.error.unknown': 'Die Kommunikation mit dem CMS ist aufgrund eines unbekannten Fehlers fehlgeschlagen.',
28142
- 'ajax.error.production': 'Bei Ihrer letzten Aktion ist ein technischer Fehler aufgetreten. Bitte versuchen Sie es später noch einmal. Falls das Problem bestehen bleibt, wenden Sie sich bitte an Ihren technischen Ansprechpartner für diese Website.',
29511
+ 'ajax.error.message_for_editor': 'Bei Ihrer letzten Aktion ist ein technischer Fehler aufgetreten. Bitte versuchen Sie es später noch einmal. Falls das Problem bestehen bleibt, wenden Sie sich bitte an Ihren technischen Ansprechpartner für diese Website und geben Sie bitte die teschnischen Details an.',
28143
29512
 
28144
29513
  'workspace_limit_exceeded.message': 'In Ihrem Tarif sind keine weiteren Arbeitskopien verfügbar. Bitte wechseln Sie den Tarif.',
28145
29514
 
28146
- 'warn_before_unloading': 'Sie haben nicht gespeicherte Änderungen! Sind Sie sicher, dass sie schließen wollen?'
29515
+ 'warn_before_unloading': 'Sie haben nicht gespeicherte Änderungen! Sind Sie sicher, dass sie schließen wollen?',
29516
+
29517
+ 'widgetlist_field_element.markup_error': 'Scrivito hat festgestellt, dass einer der Widgets invalides Markup aufweist. Bitte laden Sie die Seite neu und versuchen es noch einmal. Falls das Problem bestehen bleibt, wenden Sie sich bitte an Ihren technischen Ansprechpartner für diese Website.'
28147
29518
  }, 'de');
28148
29519
  $.i18n().load({
28149
29520
  'confirm': 'Confirm',
@@ -28280,21 +29651,26 @@ $.i18n().load({
28280
29651
  'current_page_link_dialog.title': 'Share this page',
28281
29652
  'current_page_link_dialog.description': 'Using the URL below, you can share the current page as part of this working copy. The recipients need to be logged in and have access to the working copy.',
28282
29653
 
29654
+ 'error_dialog.toggle_details': 'Toggle details',
29655
+ 'error_dialog.error_details': 'Error details',
29656
+
28283
29657
  'commands.current_page_link.title': 'Share this page',
28284
29658
  'commands.current_page_link.is_deleted': 'A deleted page cannot be shared because it is inaccessible in preview mode',
28285
29659
 
28286
- 'commands.create_workspace.forbidden': 'You can not create a workspace due to missing user permissions.',
29660
+ 'commands.create_workspace.forbidden': 'You cannot create a workspace due to missing user permissions.',
28287
29661
  'commands.create_workspace.title': 'Create working copy',
28288
29662
  'commands.create_workspace.dialog.title': 'Create working copy',
28289
29663
  'commands.create_workspace.dialog.description': 'Please enter the title of the new working copy.',
28290
29664
  'commands.create_workspace.dialog.placeholder': 'new title',
28291
29665
  'commands.create_workspace.dialog.accept': 'Create',
28292
29666
 
29667
+ 'commands.rename_workspace.forbidden': 'You cannot rename the workspace due to missing user permissions.',
28293
29668
  'commands.rename_workspace.title': 'Rename',
28294
29669
  'commands.rename_workspace.dialog.title': 'Rename "$1"',
28295
29670
  'commands.rename_workspace.dialog.description': 'Please enter the new title of the working copy.',
28296
29671
  'commands.rename_workspace.dialog.accept': 'Rename',
28297
29672
 
29673
+ 'commands.rebase_workspace.forbidden': 'You cannot rebase the workspace due to missing user permissions.',
28298
29674
  'commands.rebase_workspace.title': 'Update',
28299
29675
  'commands.rebase_workspace.tooltip': 'Working copy "$1" is outdated. Please update it.',
28300
29676
  'commands.rebase_workspace.uptodate': 'Working copy "$1" is up to date.',
@@ -28302,11 +29678,13 @@ $.i18n().load({
28302
29678
  'commands.rebase_workspace.has_conflicts.description': 'Your working copy could not be fully updated. Some of its content has also been altered in a different working copy that has been published in the meantime. Please refer to the changes list for details.',
28303
29679
  'commands.rebase_workspace.open_changes_dialog': 'Show changes',
28304
29680
 
29681
+ 'commands.delete_workspace.forbidden': 'You cannot delete the workspace due to missing user permissions.',
28305
29682
  'commands.delete_workspace.title': 'Delete',
28306
29683
  'commands.delete_workspace.dialog.title': 'Really delete "$1"?',
28307
29684
  'commands.delete_workspace.dialog.description': 'A deleted working copy cannot be restored.',
28308
29685
  'commands.delete_workspace.dialog.confirm': 'Delete',
28309
29686
 
29687
+ 'commands.workspace_settings.forbidden': 'You cannot change the settings of the workspace due to missing user permissions.',
28310
29688
  'commands.workspace_settings.title': 'Edit settings',
28311
29689
  'commands.workspace_settings.dialog.title': 'Settings for "$1"',
28312
29690
 
@@ -28388,9 +29766,6 @@ $.i18n().load({
28388
29766
  'commands.choose_and_create_widget.disabled': 'You cannot insert any widgets here.',
28389
29767
  'commands.create_widget.title': 'Insert $1',
28390
29768
 
28391
- 'commands.add_content.title': 'Insert content',
28392
- 'commands.add_content.not_allowed': 'It is not allowed to insert random content into this field.',
28393
-
28394
29769
  'commands.widget_details.title': 'Widget properties',
28395
29770
  'commands.widget_details.no_details_view': 'This widget has no properties',
28396
29771
  'commands.widget_details.dialog.title': 'Properties of "$1"',
@@ -28427,20 +29802,21 @@ $.i18n().load({
28427
29802
 
28428
29803
  'ajax.error': 'Communication with the CMS failed with error: $1',
28429
29804
  'ajax.error.communication': 'Communication with the CMS failed. Please check your network connectivity.',
28430
- 'ajax.error.unknown': 'Communication with the CMS failed for unknown reasons.',
28431
- 'ajax.error.production': 'During your last action, a technical error occurred. Please try again later. If the problem persists, please contact a technician familiar with this website.',
29805
+ 'ajax.error.message_for_editor': 'During your last action, a technical error occurred. Please try again later. If the problem persists, please contact a technician familiar with this website and provide the error details.',
28432
29806
 
28433
29807
  'workspace_limit_exceeded.message': 'You have reached the maximum number of working copies included in your plan. Please consider to have your plan upgraded.',
28434
29808
 
28435
29809
  'warn_before_unloading': 'You have unsaved changes. Are you sure you want to quit?',
28436
29810
 
29811
+ 'widgetlist_field_element.markup_error': 'Scrivito found a widget with invalid markup. Please reload the page and try again. If the problem persists, please contact a technician familiar with this website.',
29812
+
28437
29813
  'test.two_arguments': '$1, $2',
28438
29814
  'test.four_arguments': '$1, $2, $3, $4'
28439
29815
  }, 'en');
28440
29816
  /* global alert:false */
28441
29817
 
28442
29818
 
28443
- var scrivito = {};
29819
+ var scrivito = {}; // jshint ignore:line
28444
29820
 
28445
29821
  (function() {
28446
29822
  var inited = false;
@@ -28498,10 +29874,24 @@ var scrivito = {};
28498
29874
  }
28499
29875
  },
28500
29876
 
28501
- log_error: function(message, exception) {
28502
- if (window.console) {
28503
- window.console.error(message, exception);
29877
+ log_error: function() {
29878
+ if (window.console) {
29879
+ window.console.error.apply(window.console, arguments);
29880
+ }
29881
+ },
29882
+
29883
+ throw_error: function(message, options) {
29884
+ options = options || {};
29885
+
29886
+ var params = options.params || [];
29887
+ params.unshift(message);
29888
+ scrivito.log_error.apply(null, params);
29889
+
29890
+ if (options.description) {
29891
+ scrivito.alert_dialog(options.description);
28504
29892
  }
29893
+
29894
+ $.error(message);
28505
29895
  },
28506
29896
 
28507
29897
  redirect_to: function(location, target_window) {
@@ -28894,7 +30284,6 @@ var scrivito = {};
28894
30284
  scrivito.external_links.init();
28895
30285
 
28896
30286
  scrivito.widget_reloading.init();
28897
- scrivito.widget_sorting.init();
28898
30287
 
28899
30288
  scrivito.no_turbolinks.init();
28900
30289
 
@@ -28905,6 +30294,12 @@ var scrivito = {};
28905
30294
 
28906
30295
  scrivito.reloading.init();
28907
30296
 
30297
+ if (window.location.hash === '#__scrivito_enable_drag_n_drool') {
30298
+ scrivito.drag_n_drool.init();
30299
+ } else {
30300
+ scrivito.widget_sorting.init();
30301
+ }
30302
+
28908
30303
  window.onbeforeunload = scrivito.warn_before_unloading;
28909
30304
 
28910
30305
  scrivito.url_update(scrivito.application_window, scrivito.cms_window.from(window));
@@ -29254,16 +30649,16 @@ var scrivito = {};
29254
30649
  };
29255
30650
  }());
29256
30651
  (function() {
30652
+ var permissions;
30653
+
29257
30654
  _.extend(scrivito, {
29258
30655
  user_permissions: {
29259
- permissions_hash: {},
29260
-
29261
- init: function(permissions_hash) {
29262
- scrivito.user_permissions.permissions_hash = permissions_hash;
30656
+ init: function(config) {
30657
+ permissions = config;
29263
30658
  },
29264
30659
 
29265
- can: function(permission_key) {
29266
- return !!scrivito.user_permissions.permissions_hash[permission_key];
30660
+ can: function(action) {
30661
+ return permissions && permissions[action];
29267
30662
  }
29268
30663
  }
29269
30664
  });
@@ -29302,23 +30697,12 @@ var scrivito = {};
29302
30697
  }, options || {})).then(
29303
30698
  function(result, text_status, xhr) {
29304
30699
  return $.Deferred().resolve(result);
29305
- }, function(xhr, text_status, error) {
29306
- var error_message;
29307
- var error_code;
30700
+ }, function(xhr, text_status, xhr_error) {
29308
30701
  try {
29309
- var error_json = JSON.parse(xhr.responseText);
29310
- error_message = error_json.error;
29311
- error_code = error_json.code;
29312
- } catch (SyntaxError) {}
29313
-
29314
- if (!error_message) {
29315
- error_message = error;
30702
+ return $.Deferred().reject(JSON.parse(xhr.responseText));
30703
+ } catch (SyntaxError) {
30704
+ return $.Deferred().reject(xhr_error);
29316
30705
  }
29317
- return $.Deferred().reject({
29318
- status: xhr.status,
29319
- message: error_message,
29320
- code: error_code
29321
- });
29322
30706
  }
29323
30707
  );
29324
30708
  };
@@ -29356,23 +30740,23 @@ var scrivito = {};
29356
30740
  },
29357
30741
 
29358
30742
  display_ajax_error: function(error) {
29359
- var ajax_error = error.message;
29360
- var error_message;
29361
- if (_.contains(['abort', 'parsererror', 'timeout'], ajax_error)) {
29362
- error_message = scrivito.t('ajax.error.communication');
29363
- } else if (ajax_error === 'error') {
29364
- error_message = scrivito.t('ajax.error.unknown');
29365
- } else if (ajax_error) {
29366
- error_message = scrivito.t('ajax.error', ajax_error);
30743
+ var message, message_for_editor;
30744
+
30745
+ if (_.isObject(error)) {
30746
+ message = scrivito.t('ajax.error', error.message);
30747
+ message_for_editor = error.message_for_editor;
30748
+ } else if (_.contains(['abort', 'parsererror', 'timeout'], error)) {
30749
+ message = scrivito.t('ajax.error.communication');
29367
30750
  } else {
29368
- error_message = scrivito.t('ajax.error.unknown');
30751
+ message = scrivito.t('ajax.error', error);
29369
30752
  }
29370
30753
 
29371
30754
  if (scrivito.is_development_mode) {
29372
- scrivito.alert_dialog(error_message);
30755
+ scrivito.alert_dialog(message);
29373
30756
  } else {
29374
- scrivito.log_error(error_message);
29375
- scrivito.info_dialog(scrivito.t('ajax.error.production'));
30757
+ scrivito.log_error(message);
30758
+ scrivito.error_dialog(message_for_editor || scrivito.t('ajax.error.message_for_editor'),
30759
+ [error.timestamp, message]);
29376
30760
  }
29377
30761
  }
29378
30762
  });
@@ -29570,7 +30954,8 @@ var scrivito = {};
29570
30954
  var menu = cms_element.menu();
29571
30955
  _.find(menu, function(command, index) {
29572
30956
  if (command.id() === id) {
29573
- return menu[index] = scrivito.command.create_instance(_.extend(params, {id: id}));
30957
+ menu[index] = scrivito.command.create_instance(_.extend(params, {id: id}));
30958
+ return menu[index];
29574
30959
  }
29575
30960
  });
29576
30961
  cms_element.set_menu(menu);
@@ -30462,6 +31847,124 @@ var scrivito = {};
30462
31847
  }
30463
31848
  });
30464
31849
  }());
31850
+ (function() {
31851
+ _.extend(scrivito, {
31852
+ path_for_id: function(id) {
31853
+ return '/__scrivito/' + id;
31854
+ },
31855
+
31856
+ id_from_path: function(url) {
31857
+ var match = /__scrivito\/([a-z0-9]{16})/.exec(url);
31858
+
31859
+ if (match) {
31860
+ return match[1];
31861
+ }
31862
+ }
31863
+ });
31864
+ })();
31865
+ (function() {
31866
+ _.extend(scrivito, {
31867
+ serialize_obj: function(obj_id, attrs) {
31868
+ return serialize_widget_pool(obj_id, attrs._widget_pool).then(function(widget_pool) {
31869
+ return serialize_attrs(obj_id, attrs).then(function(serialized_attrs) {
31870
+ serialized_attrs._widget_pool = widget_pool;
31871
+ return serialized_attrs;
31872
+ });
31873
+ });
31874
+ }
31875
+ });
31876
+
31877
+ var serialize_widget_pool = function(obj_id, widget_pool) {
31878
+ if (widget_pool) {
31879
+ var promises = _.map(widget_pool, function(attrs, widget_id) {
31880
+ return serialize_attrs(obj_id, attrs).then(function(serialized_attrs) {
31881
+ return [widget_id, serialized_attrs];
31882
+ });
31883
+ });
31884
+
31885
+ return $.when.apply(this, promises).then(function() {
31886
+ return _.object(arguments);
31887
+ });
31888
+ } else {
31889
+ return $.Deferred().resolve(widget_pool);
31890
+ }
31891
+ };
31892
+
31893
+ var serialize_attrs = function(obj_id, attrs) {
31894
+ var promises = _.map(attrs, function(attr_value, attr_name) {
31895
+ return serialize_attr(obj_id, attr_name, attr_value);
31896
+ });
31897
+
31898
+ return $.when.apply(this, promises).then(function() {
31899
+ return _.object(arguments);
31900
+ });
31901
+ };
31902
+
31903
+ var serialize_attr = function(obj_id, attr_name, attr_value) {
31904
+ if (is_file(attr_value)) {
31905
+ return serialize_file(obj_id, attr_name, attr_value);
31906
+ }
31907
+
31908
+ if (is_binary(attr_value)) {
31909
+ return serialize_binary(attr_name, attr_value);
31910
+ }
31911
+
31912
+ if (is_copied_binary(attr_value)) {
31913
+ return serialize_copied_binary(attr_name, attr_value);
31914
+ }
31915
+
31916
+ if (is_uploaded_binary(attr_value)) {
31917
+ return serialize_uploaded_binary(obj_id, attr_name, attr_value);
31918
+ }
31919
+
31920
+ return $.Deferred().resolve([attr_name, scrivito.obj.serialize_value(attr_value)]);
31921
+ };
31922
+
31923
+ var is_file = function(object) {
31924
+ return object &&
31925
+ _.isFunction(object.slice) &&
31926
+ _.isDate(object.lastModifiedDate) &&
31927
+ _.isString(object.name);
31928
+ };
31929
+
31930
+ var serialize_file = function(obj_id, attr_name, attr_value) {
31931
+ return scrivito.blob.create(obj_id, {file: attr_value}).then(function(blob) {
31932
+ return [attr_name, blob];
31933
+ });
31934
+ };
31935
+
31936
+ var is_binary = function(object) {
31937
+ return object && object.url && object.filename && _.isFunction(object.copy);
31938
+ };
31939
+
31940
+ var serialize_binary = function(attr_name, attr_value) {
31941
+ return serialize_copied_binary(attr_name, attr_value.copy());
31942
+ };
31943
+
31944
+ var is_copied_binary = function(object) {
31945
+ return object && object.is_copied_binary;
31946
+ };
31947
+
31948
+ var serialize_copied_binary = function(attr_name, attr_value) {
31949
+ return [attr_name, {copy: {
31950
+ obj_id: attr_value.obj_id,
31951
+ widget_id: attr_value.widget_id,
31952
+ attribute_name: attr_value.attr_name,
31953
+ filename: attr_value.filename,
31954
+ content_type: attr_value.content_type
31955
+ }}];
31956
+ };
31957
+
31958
+ var is_uploaded_binary = function(object) {
31959
+ return object && object.is_uploaded_binary;
31960
+ };
31961
+
31962
+ var serialize_uploaded_binary = function(obj_id, attr_name, attr_value) {
31963
+ return scrivito.blob.create(obj_id, attr_value).then(function(blob) {
31964
+ return [attr_name, blob];
31965
+ });
31966
+ };
31967
+ }());
30465
31968
  (function() {
30466
31969
  var expando = "scrivito_cms_element";
30467
31970
 
@@ -30702,7 +32205,7 @@ var scrivito = {};
30702
32205
  from: function(dom_element) {
30703
32206
  var element_document;
30704
32207
 
30705
- if (!dom_element.jquery) { $.error("not a jquery instance"); }
32208
+ if (!dom_element.jquery) { dom_element = $(dom_element); }
30706
32209
  if (dom_element.length === 0) {
30707
32210
  $.error("empty jquery instance given");
30708
32211
  }
@@ -30768,6 +32271,8 @@ var scrivito = {};
30768
32271
 
30769
32272
  suggest_completion: scrivito.suggest_completion,
30770
32273
  description_for_editor: scrivito.description_for_editor, // @api protected
32274
+ path_for_id: scrivito.path_for_id,
32275
+ id_from_path: scrivito.id_from_path,
30771
32276
 
30772
32277
  // @api protected
30773
32278
  dialog: function(content, options) {
@@ -30833,7 +32338,7 @@ var scrivito = {};
30833
32338
 
30834
32339
  // Return offset of given element relative to scrivito window.
30835
32340
  offset: function(dom_element) {
30836
- var element_offset = dom_element.offset();
32341
+ var element_offset = $(dom_element).offset();
30837
32342
  var iframe_offset = $(that.window().iframe()).offset();
30838
32343
  if (iframe_offset) {
30839
32344
  return {
@@ -31096,9 +32601,30 @@ var scrivito = {};
31096
32601
  if (value && field_type === 'date') {
31097
32602
  var DateClass = scrivito.cms_document.from(that.dom_element()).browser_window().Date;
31098
32603
  return new DateClass(value);
31099
- } else {
31100
- return value;
31101
32604
  }
32605
+
32606
+ if (field_type === 'binary') {
32607
+ return _.extend(value, {
32608
+ no_cache_url: function() {
32609
+ var path = 'objs/'+that.obj().id()+'/binary_no_cache?'+
32610
+ $.param({attribute_name: that.field_name()});
32611
+ return scrivito.ajax('GET', path).then(function(response) {
32612
+ return response.no_cache_url;
32613
+ });
32614
+ },
32615
+
32616
+ copy: function(params) {
32617
+ return _.extend({
32618
+ is_copied_binary: true,
32619
+ obj_id: that.obj().id(),
32620
+ widget_id: that.widget() && that.widget().id(),
32621
+ attr_name: that.field_name()
32622
+ }, params || {});
32623
+ }
32624
+ });
32625
+ }
32626
+
32627
+ return value;
31102
32628
  };
31103
32629
 
31104
32630
  return that;
@@ -31299,16 +32825,10 @@ var scrivito = {};
31299
32825
  scrivito.cms_element.definitions.push(scrivito.html_field_element);
31300
32826
  }());
31301
32827
  (function() {
32828
+ var write_promises = {};
32829
+
31302
32830
  _.extend(scrivito, {
31303
32831
  obj: {
31304
- serialize_value: function(value) {
31305
- if (_.isDate(value)) {
31306
- return moment.utc(value).toISOString();
31307
- } else {
31308
- return value;
31309
- }
31310
- },
31311
-
31312
32832
  create_instance: function(params) {
31313
32833
  var that = {
31314
32834
  id: function() {
@@ -31378,48 +32898,50 @@ var scrivito = {};
31378
32898
  },
31379
32899
 
31380
32900
  save: function(attrs) {
31381
- return prepare_attrs(that.id(), attrs).then(function(prepared_attrs) {
31382
- return scrivito.ajax('PUT', 'objs/'+that.id(), {data: {obj: prepared_attrs}});
32901
+ return scrivito.serialize_obj(that.id(), attrs).then(function(serialized_attrs) {
32902
+ return that.enqueue_ajax('PUT', 'objs/'+that.id(), {data: {obj: serialized_attrs}});
31383
32903
  });
31384
32904
  },
31385
32905
 
31386
32906
  destroy: function() {
31387
- return scrivito.ajax('DELETE', 'objs/' + that.id()).then(function(result) {
32907
+ return that.enqueue_ajax('DELETE', 'objs/'+that.id()).then(function(result) {
31388
32908
  return result.redirect_to;
31389
32909
  });
31390
32910
  },
31391
32911
 
31392
32912
  destroy_widget: function(widget_id) {
31393
- return scrivito.ajax('PUT',
31394
- 'objs/' + that.id() + '/destroy_widget?widget_id=' + widget_id);
32913
+ return that.enqueue_ajax('PUT',
32914
+ 'objs/'+that.id()+'/destroy_widget?widget_id='+widget_id);
31395
32915
  },
31396
32916
 
31397
32917
  revert: function() {
31398
- return scrivito.ajax('PUT', 'objs/' + that.id() + '/revert');
32918
+ return that.enqueue_ajax('PUT', 'objs/'+that.id()+'/revert');
31399
32919
  },
31400
32920
 
31401
32921
  revert_widget: function(widget_id) {
31402
- return scrivito.ajax('PUT', 'objs/'+that.id()+'/revert_widget?widget_id='+widget_id);
32922
+ return that.enqueue_ajax('PUT',
32923
+ 'objs/'+that.id()+'/revert_widget?widget_id='+widget_id);
31403
32924
  },
31404
32925
 
31405
32926
  conflicting_workspaces: function() {
31406
- return scrivito.ajax('GET', 'objs/' + that.id() + '/conflicting_workspaces').then(
31407
- function(workspace_datas) {
31408
- return scrivito.workspace.from_data_collection(workspace_datas);
31409
- });
32927
+ return that.enqueue_ajax('GET', 'objs/'+that.id()+'/conflicting_workspaces')
32928
+ .then(function(workspace_datas) {
32929
+ return scrivito.workspace.from_data_collection(workspace_datas);
32930
+ });
31410
32931
  },
31411
32932
 
31412
32933
  is_outdated: function() {
31413
- return scrivito.ajax('GET', 'objs/' + that.id() + '/is_outdated').then(
31414
- function(result) { return result.is_outdated; });
32934
+ return that.enqueue_ajax('GET', 'objs/'+that.id()+'/is_outdated')
32935
+ .then(function(result) { return result.is_outdated; });
31415
32936
  },
31416
32937
 
31417
32938
  restore: function() {
31418
- return scrivito.ajax('PUT', 'objs/' + that.id() + '/restore');
32939
+ return that.enqueue_ajax('PUT', 'objs/'+that.id()+'/restore');
31419
32940
  },
31420
32941
 
31421
32942
  restore_widget: function(widget_id) {
31422
- return scrivito.ajax('PUT', 'objs/'+that.id()+'/restore_widget?widget_id='+widget_id);
32943
+ return that.enqueue_ajax('PUT',
32944
+ 'objs/'+that.id()+'/restore_widget?widget_id='+widget_id);
31423
32945
  },
31424
32946
 
31425
32947
  details_src: function() {
@@ -31428,36 +32950,51 @@ var scrivito = {};
31428
32950
  },
31429
32951
 
31430
32952
  mark_resolved: function() {
31431
- return scrivito.ajax('PUT', 'objs/' + that.id() + '/mark_resolved');
32953
+ return that.enqueue_ajax('PUT', 'objs/'+that.id()+'/mark_resolved');
31432
32954
  },
31433
32955
 
31434
32956
  copy_to: function(path) {
31435
32957
  var attrs = {data: {parent_path: path}};
31436
- return scrivito.ajax('POST', 'objs/'+that.id()+'/copy', attrs).then(function(data) {
31437
- return scrivito.obj.create_instance(data);
31438
- });
32958
+ return that.enqueue_ajax('POST', 'objs/'+that.id()+'/copy', attrs)
32959
+ .then(function(data) { return scrivito.obj.create_instance(data); });
31439
32960
  },
31440
32961
 
31441
32962
  duplicate: function() {
31442
- return scrivito.ajax('POST', 'objs/'+that.id()+'/duplicate').then(function(data) {
31443
- return scrivito.obj.create_instance(data);
31444
- });
32963
+ return that.enqueue_ajax('POST', 'objs/'+that.id()+'/duplicate')
32964
+ .then(function(data) { return scrivito.obj.create_instance(data); });
31445
32965
  },
31446
32966
 
31447
32967
  transfer_modifications_to: function(workspace_id) {
31448
- return scrivito.ajax('PUT', 'objs/'+that.id()+'/transfer_modifications',
32968
+ return that.enqueue_ajax('PUT', 'objs/'+that.id()+'/transfer_modifications',
31449
32969
  {data: {workspace_id: workspace_id}});
31450
32970
  },
31451
32971
 
31452
32972
  reload: function() {
31453
- return scrivito.ajax('GET', 'objs/'+that.id()).then(function(data) {
32973
+ return that.enqueue_ajax('GET', 'objs/'+that.id()).then(function(data) {
31454
32974
  params.has_conflict = data.has_conflict;
31455
32975
  params.modification = data.modification;
31456
32976
  });
31457
32977
  },
31458
32978
 
31459
32979
  reload_widget: function(widget_id) {
31460
- return scrivito.ajax('GET', 'objs/'+that.id()+'/widget?widget_id='+widget_id);
32980
+ return that.enqueue_ajax('GET', 'objs/'+that.id()+'/widget?widget_id='+widget_id);
32981
+ },
32982
+
32983
+ enqueue_ajax: function() {
32984
+ var args = arguments;
32985
+ var ajax = function() { return scrivito.ajax.apply(null, args); };
32986
+
32987
+ if (args[0] === 'GET') { return ajax(); }
32988
+
32989
+ var promise = $.Deferred();
32990
+ (write_promises[that.id()] || $.Deferred().resolve()).always(function() {
32991
+ ajax().then(
32992
+ function() { promise.resolve.apply(promise, arguments); },
32993
+ function() { promise.reject.apply(promise, arguments); }
32994
+ );
32995
+ });
32996
+ write_promises[that.id()] = promise;
32997
+ return promise;
31461
32998
  }
31462
32999
  };
31463
33000
 
@@ -31483,7 +33020,8 @@ var scrivito = {};
31483
33020
  return scrivito.ajax('GET', path).then(function(selection) {
31484
33021
  var names = _.pluck(selection, 'name');
31485
33022
  var recent = scrivito.obj_class_selection.recent(names);
31486
- var popular = _.intersection(scrivito.popular_obj_classes, names);
33023
+ var all_popular_valid_obj_classes = _.intersection(scrivito.popular_obj_classes, names);
33024
+ var popular = _.take(all_popular_valid_obj_classes, 5);
31487
33025
  return {
31488
33026
  all: _.sortBy(selection, 'name'),
31489
33027
  recent: _.map(recent, function(name) { return _.findWhere(selection, {name: name}); }),
@@ -31498,10 +33036,11 @@ var scrivito = {};
31498
33036
 
31499
33037
  create: function(attrs) {
31500
33038
  attrs._id = scrivito.random_id();
31501
- return prepare_attrs(attrs._id, attrs).then(function(prepared_attrs) {
31502
- return scrivito.ajax('POST', 'objs', {data: {obj: prepared_attrs}}).then(function(data) {
31503
- scrivito.obj_class_selection.store(prepared_attrs._obj_class);
31504
- return scrivito.obj.create_instance(data);
33039
+ return scrivito.serialize_obj(attrs._id, attrs).then(function(serialized_attrs) {
33040
+ var params = {data: {obj: serialized_attrs}};
33041
+ return scrivito.ajax('POST', 'objs', params).then(function(obj_data) {
33042
+ scrivito.obj_class_selection.store(serialized_attrs._obj_class);
33043
+ return scrivito.obj.create_instance(obj_data);
31505
33044
  });
31506
33045
  });
31507
33046
  },
@@ -31512,60 +33051,22 @@ var scrivito = {};
31512
33051
  if (result.status !== 'success') { return {obj: obj, reason: result.reason}; }
31513
33052
  });
31514
33053
  })).then(function() { return $.Deferred().resolve(_.compact(arguments)); });
31515
- }
31516
- }
31517
- });
33054
+ },
31518
33055
 
31519
- var is_file = function(object) {
31520
- return object &&
31521
- _.isFunction(object.slice) &&
31522
- _.isDate(object.lastModifiedDate) &&
31523
- _.isString(object.name);
31524
- };
33056
+ serialize_value: function(value) {
33057
+ if (_.isDate(value)) {
33058
+ return moment.utc(value).toISOString();
33059
+ } else {
33060
+ return value;
33061
+ }
33062
+ },
31525
33063
 
31526
- var convert_attrs = function(obj_id, attrs) {
31527
- var collected_promises = _.map(attrs, function(value, field_name) {
31528
- if (is_file(value)) {
31529
- return scrivito.blob.create(obj_id, {file: value}).then(function(blob) {
31530
- return [field_name, blob];
31531
- });
31532
- } else if (value && value.is_uploaded_binary) {
31533
- return scrivito.blob.create(obj_id, value).then(function(blob) {
31534
- return [field_name, blob];
31535
- });
33064
+ // For test purpose only.
33065
+ clear_write_promises: function() {
33066
+ write_promises = {};
31536
33067
  }
31537
- return $.Deferred().resolve([field_name, scrivito.obj.serialize_value(value)]);
31538
- });
31539
-
31540
- return $.when.apply(this, collected_promises).then(function() {
31541
- return _.object(arguments);
31542
- });
31543
- };
31544
-
31545
- var convert_widget_pool = function(obj_id, widget_pool) {
31546
- if (widget_pool) {
31547
- var conversion_promises = _.map(widget_pool, function(attrs, widget_id) {
31548
- return convert_attrs(obj_id, attrs).then(function(converted_attrs) {
31549
- return [widget_id, converted_attrs];
31550
- });
31551
- });
31552
-
31553
- return $.when.apply(this, conversion_promises).then(function() {
31554
- return _.object(arguments);
31555
- });
31556
- } else {
31557
- return $.Deferred().resolve(widget_pool);
31558
33068
  }
31559
- };
31560
-
31561
- var prepare_attrs = function(obj_id, attrs) {
31562
- return convert_widget_pool(obj_id, attrs._widget_pool).then(function(widget_pool) {
31563
- return convert_attrs(obj_id, attrs).then(function(converted_attrs) {
31564
- converted_attrs._widget_pool = widget_pool;
31565
- return converted_attrs;
31566
- });
31567
- });
31568
- };
33069
+ });
31569
33070
  }());
31570
33071
  (function() {
31571
33072
  _.extend(scrivito, {
@@ -31614,8 +33115,9 @@ var scrivito = {};
31614
33115
  (function() {
31615
33116
  _.extend(scrivito, {
31616
33117
  chainable_search: {
31617
- create_instance: function(build_query) {
33118
+ create_instance: function(build_query, continuation, fetched_ids) {
31618
33119
  var query = build_query || {predicates: []};
33120
+ fetched_ids = fetched_ids || [];
31619
33121
 
31620
33122
  var add_predicate = function(field, operator, value, boost, negate) {
31621
33123
  var new_query = {
@@ -31637,8 +33139,13 @@ var scrivito = {};
31637
33139
  };
31638
33140
 
31639
33141
  var execute_search = function(query, action) {
31640
- return scrivito.ajax('GET', 'objs/search?' +
31641
- $.param({query: JSON.stringify(query), query_action: action}));
33142
+ var get_params = { query: JSON.stringify(query), query_action: action };
33143
+
33144
+ if (continuation) {
33145
+ get_params.continuation = continuation;
33146
+ }
33147
+
33148
+ return scrivito.ajax('GET', 'objs/search?' + $.param(get_params));
31642
33149
  };
31643
33150
 
31644
33151
  var that = {
@@ -31672,18 +33179,23 @@ var scrivito = {};
31672
33179
 
31673
33180
  // @api public
31674
33181
  order: function(order) {
31675
- query.order = order;
33182
+ if (_.isString(order)) {
33183
+ query.order = [order, 'asc'];
33184
+ } else {
33185
+ query.order = _.first(_.pairs(order));
33186
+ }
33187
+
31676
33188
  return that;
31677
33189
  },
31678
33190
 
31679
33191
  // @api public
31680
33192
  reverse_order: function() {
31681
- if (query.reverse_order) {
31682
- delete query.reverse_order;
33193
+ if (query.order) {
33194
+ query.order[1] = query.order[1] === 'asc' ? 'desc' : 'asc';
33195
+ return that;
31683
33196
  } else {
31684
- query.reverse_order = true;
33197
+ $.error("A search order has to be specified before reverse_order can be applied.");
31685
33198
  }
31686
- return that;
31687
33199
  },
31688
33200
 
31689
33201
  // @api public
@@ -31720,16 +33232,23 @@ var scrivito = {};
31720
33232
  return execute_search(query).then(function(result) {
31721
33233
  var batch_size = result.hits.length;
31722
33234
  var total_matches = result.total;
33235
+ var next_continuation = result.continuation;
33236
+
33237
+ result = filter_duplicates(result, fetched_ids);
31723
33238
 
31724
- if (total_matches > (batch_size + offset)) {
31725
- var next_offset = offset + batch_size;
31726
- var next_query = _.extend({}, query, {offset: next_offset});
31727
- next = scrivito.chainable_search.create_instance(next_query);
33239
+ if (next_continuation) {
33240
+ next = scrivito.chainable_search.create_instance(
33241
+ query,
33242
+ next_continuation,
33243
+ result.fetched_ids
33244
+ );
31728
33245
  } else {
33246
+ total_matches = result.fetched_ids.length;
31729
33247
  next = undefined;
31730
33248
  }
31731
33249
 
31732
- return $.Deferred().resolve(result, next);
33250
+ var public_result = {total: total_matches, hits: result.hits};
33251
+ return $.Deferred().resolve(public_result, next);
31733
33252
  });
31734
33253
  },
31735
33254
 
@@ -31754,6 +33273,22 @@ var scrivito = {};
31754
33273
 
31755
33274
  });
31756
33275
 
33276
+ var filter_duplicates = function(result, fetched_ids) {
33277
+ var filtered_result = {
33278
+ hits: [],
33279
+ fetched_ids: _.clone(fetched_ids || [])
33280
+ };
33281
+
33282
+ _.each(result.hits, function(hit) {
33283
+ if(!_.contains(filtered_result.fetched_ids, hit.id)) {
33284
+ filtered_result.hits.push(hit.serialized_obj);
33285
+ filtered_result.fetched_ids.push(hit.id);
33286
+ }
33287
+ });
33288
+
33289
+ return filtered_result;
33290
+ };
33291
+
31757
33292
  var serialize_values = function(values) {
31758
33293
  if (!_.isArray(values)) {
31759
33294
  values = [values];
@@ -32063,12 +33598,21 @@ var scrivito = {};
32063
33598
  },
32064
33599
 
32065
33600
  widget_elements: function() {
32066
- var widget_elements_dom = that.dom_element()
32067
- .children('[data-scrivito-private-widget-id]');
32068
- var widget_elements = _.map(widget_elements_dom, function(widget_element_dom) {
32069
- return scrivito.cms_element.from_dom_element($(widget_element_dom));
33601
+ return _.map(that.dom_element().children(), function(element) {
33602
+ var dom_element = $(element);
33603
+ if (dom_element.is('[data-scrivito-private-widget-id]')) {
33604
+ return scrivito.cms_element.from_dom_element(dom_element);
33605
+ } else {
33606
+ // Remove the "scrivito_skip_widget_markup_validation"-hack after drag_n_drool
33607
+ // took place of widget_sorting.
33608
+ if (!dom_element.hasClass('scrivito_skip_widget_markup_validation')) {
33609
+ scrivito.throw_error('Scrivito found a widget with invalid markup', {
33610
+ params: [element],
33611
+ description: scrivito.t('widgetlist_field_element.markup_error')
33612
+ });
33613
+ }
33614
+ }
32070
33615
  });
32071
- return widget_elements;
32072
33616
  },
32073
33617
 
32074
33618
  is_empty: function() {
@@ -32268,12 +33812,14 @@ var scrivito = {};
32268
33812
  });
32269
33813
  },
32270
33814
 
32271
- update: function(attributes) {
32272
- return scrivito.ajax('PUT', 'workspaces/' + that.id(), {data: {workspace: attributes}});
33815
+ rename: function(title) {
33816
+ return scrivito.ajax('PUT', 'workspaces/'+that.id()+'/rename',
33817
+ {data: {workspace: {title: title}}});
32273
33818
  },
32274
33819
 
32275
- rename: function(new_title) {
32276
- return that.update({title: new_title});
33820
+ update_memberships: function(memberships) {
33821
+ return scrivito.ajax('PUT', 'workspaces/'+that.id()+'/memberships',
33822
+ {data: {workspace: {memberships: memberships}}});
32277
33823
  },
32278
33824
 
32279
33825
  destroy: function() {
@@ -32351,11 +33897,12 @@ var scrivito = {};
32351
33897
  };
32352
33898
 
32353
33899
  var handle_check_and_publish_error = function(error, retry_until_in_ms) {
32354
- if (error.code === 'precondition_not_verifiable.workspace.publish.content_state_id') {
33900
+ var backend_code = error.backend_code;
33901
+ if (backend_code === 'precondition_not_verifiable.workspace.publish.content_state_id') {
32355
33902
  // Another workspace has been published since last check.
32356
33903
  that.mark_as_outdated();
32357
33904
  return that.check_and_publish();
32358
- } else if (error.code === 'precondition_not_met.workspace.publish.content_state_id') {
33905
+ } else if (backend_code === 'precondition_not_met.workspace.publish.content_state_id') {
32359
33906
  // The workspace has been changed since last check.
32360
33907
  if (Date.now() > retry_until_in_ms) {
32361
33908
  // retried check_and_publish for too long.
@@ -32414,7 +33961,7 @@ var scrivito = {};
32414
33961
  return scrivito.silent_ajax('POST', 'workspaces', params).then(function(ws_data) {
32415
33962
  return scrivito.workspace.from_data(ws_data);
32416
33963
  }, function(error) {
32417
- if (error.code === 'precondition_not_met.workspace.create.exceeds_limit') {
33964
+ if (error.backend_code === 'precondition_not_met.workspace.create.exceeds_limit') {
32418
33965
  scrivito.workspace_limit_exceeded();
32419
33966
  } else {
32420
33967
  scrivito.display_ajax_error(error);
@@ -32460,16 +34007,37 @@ var scrivito = {};
32460
34007
  };
32461
34008
  })();
32462
34009
  (function() {
34010
+ var cache = {};
34011
+
32463
34012
  _.extend(scrivito, {
32464
34013
  suggest_completion: function(attribute, prefix) {
32465
- var param = $.param({attribute: attribute});
32466
- return scrivito.ajax('GET', 'suggest_completion?' + param).then(function(suggestions) {
34014
+ return fetch_suggestions(attribute).then(function(suggestions) {
32467
34015
  return _.filter(suggestions, function(suggestion) {
32468
34016
  return suggestion.toLowerCase().indexOf(prefix.toLowerCase()) === 0;
32469
34017
  });
32470
34018
  });
32471
34019
  }
32472
34020
  });
34021
+
34022
+ _.extend(scrivito.suggest_completion, {
34023
+ // For test purpose only.
34024
+ clear_cache: function() {
34025
+ cache = {};
34026
+ }
34027
+ });
34028
+
34029
+ var fetch_suggestions = function(attribute) {
34030
+ var suggestions = cache[attribute];
34031
+ if (suggestions) {
34032
+ return $.Deferred().resolve(suggestions);
34033
+ } else {
34034
+ var param = $.param({attribute: attribute});
34035
+ return scrivito.ajax('GET', 'suggest_completion?' + param).then(function(suggestions) {
34036
+ cache[attribute] = suggestions;
34037
+ return suggestions;
34038
+ });
34039
+ }
34040
+ };
32473
34041
  }());
32474
34042
  (function() {
32475
34043
  _.extend(scrivito, {
@@ -32600,6 +34168,7 @@ var scrivito = {};
32600
34168
  });
32601
34169
  }());
32602
34170
  /*global ScrivitoHandlebarsTemplates:false */
34171
+ /*global __hbs__:false */
32603
34172
  /*global Handlebars:false */
32604
34173
 
32605
34174
 
@@ -32633,23 +34202,28 @@ var scrivito = {};
32633
34202
 
32634
34203
  render: function(template_path, data) {
32635
34204
  var template;
32636
- if(typeof ScrivitoHandlebarsTemplates !== 'undefined') {
34205
+ if (window.ScrivitoHandlebarsTemplates) {
32637
34206
  template = ScrivitoHandlebarsTemplates[template_path];
32638
34207
  }
32639
- if(!template) {
32640
- if(scrivito.template.load_templates_from_server) {
34208
+
34209
+ if (window.__hbs__ && __hbs__[template_path]) {
34210
+ template = Handlebars.compile(__hbs__[template_path]);
34211
+ }
34212
+
34213
+ if (!template) {
34214
+ if (scrivito.template.load_templates_from_server) {
32641
34215
  template = scrivito.template.template_cache[template_path];
32642
- if(!template) {
32643
- var url = "/app/assets/javascripts/templates/" + template_path + ".hbs?" +
32644
- Math.random();
32645
- var source = jQuery.ajax(url, { async: false }).responseText;
34216
+ if (!template) {
34217
+ var url = '/app/assets/javascripts/templates/'+template_path+'.hbs?'+Math.random();
34218
+ var source = jQuery.ajax(url, {async: false}).responseText;
32646
34219
  template = Handlebars.compile(source);
32647
34220
  scrivito.template.template_cache[template_path] = template;
32648
34221
  }
32649
34222
  } else {
32650
- throw('could not load template' + template_path);
34223
+ $.error('Could not load template: '+template_path);
32651
34224
  }
32652
34225
  }
34226
+
32653
34227
  return template(data);
32654
34228
  }
32655
34229
  }
@@ -32722,14 +34296,8 @@ var scrivito = {};
32722
34296
 
32723
34297
  hide: function() {
32724
34298
  if (view) {
32725
- scrivito.transition(view, function() {
32726
- view.removeClass('scrivito_show');
32727
- }).then(function(e) {
32728
- // Remove the view only if event is triggered by a "fade-out" transition.
32729
- if (e && $(e.target).hasClass('scrivito_show')) { return; }
32730
- if (view) { view.remove(); }
32731
- view = null;
32732
- });
34299
+ view.remove();
34300
+ view = null;
32733
34301
  }
32734
34302
  },
32735
34303
 
@@ -32856,6 +34424,37 @@ var scrivito = {};
32856
34424
  }
32857
34425
  });
32858
34426
  }());
34427
+ (function() {
34428
+ _.extend(scrivito, {
34429
+ error_dialog: function(message, details) {
34430
+ var promise = $.Deferred();
34431
+
34432
+ var view = $(scrivito.template.render('error_dialog', {message: message, details: details}));
34433
+ view.appendTo($('#scrivito_editing'));
34434
+
34435
+ var close = function() {
34436
+ scrivito.dialog.close_with_transition(view);
34437
+ promise.resolve();
34438
+ return false;
34439
+ };
34440
+
34441
+ view.find('.scrivito_close').on('click', close);
34442
+ view.find('.scrivito_toggle_details').on('click', function() {
34443
+ view.find('.scrivito_modal_body').toggle();
34444
+ });
34445
+
34446
+ scrivito.dialog.open_and_center_with_transition(view);
34447
+ return scrivito.with_dialog_behaviour(view, promise, {enter: close, escape: close});
34448
+ }
34449
+ });
34450
+
34451
+ _.extend(scrivito.error_dialog, {
34452
+ // For test purpose only.
34453
+ remove_all: function() {
34454
+ $('.scrivito_error_dialog').remove();
34455
+ }
34456
+ });
34457
+ }());
32859
34458
  (function() {
32860
34459
  _.extend(scrivito, {
32861
34460
  confirmation_dialog: function(options) {
@@ -33013,14 +34612,7 @@ var scrivito = {};
33013
34612
  init: function() {
33014
34613
  scrivito.gui.on('document', function(cms_document) {
33015
34614
  var body = cms_document.dom_element().find('body');
33016
-
33017
34615
  $(body).on('reload.scrivito', function() { cms_document.window().reload(); });
33018
-
33019
- // TODO: remove this in 1.0.0.
33020
- cms_document.local_jquery(body).on('scrivito_reload', function() {
33021
- scrivito.deprecation_warning('$.trigger("scrivito_reload")', '$.scrivito("reload")');
33022
- cms_document.window().reload();
33023
- });
33024
34616
  });
33025
34617
  }
33026
34618
  }
@@ -33387,7 +34979,7 @@ var scrivito = {};
33387
34979
  scrivito.restore_obj_command(obj, 'resource_dialog.commands.restore_obj'),
33388
34980
  scrivito.mark_resolved_obj_command(obj, 'resource_dialog.commands.mark_resolved_obj'),
33389
34981
  scrivito.delete_obj_command(obj, 'resource_dialog.commands.delete_obj',
33390
- return_to || '/'+scrivito.application_document().page().id())
34982
+ return_to || scrivito.path_for_id(scrivito.application_document().page().id()))
33391
34983
  ]);
33392
34984
  }
33393
34985
  }
@@ -33545,56 +35137,6 @@ var scrivito = {};
33545
35137
  }
33546
35138
  });
33547
35139
  }());
33548
- (function() {
33549
- _.extend(scrivito, {
33550
- add_content_command: function(cms_element) {
33551
- var widgetlist_field_element, widget_element;
33552
- if (cms_element.widget_field) {
33553
- widget_element = cms_element;
33554
- } else {
33555
- widgetlist_field_element = cms_element;
33556
- }
33557
-
33558
- return scrivito.command.create_instance({
33559
- id: 'scrivito.sdk.add_content',
33560
- title: scrivito.t('commands.add_content.title'),
33561
- icon: '&#xf082;',
33562
-
33563
- present: function() {
33564
- return scrivito.select_content && scrivito.editing_context.is_editing_mode() &&
33565
- (widget_element || widgetlist_field_element.is_empty());
33566
- },
33567
-
33568
- disabled: function() {
33569
- if (!(widgetlist_field_element || widget_element.widget_field())
33570
- .is_content_widget_allowed()) {
33571
- return scrivito.t('commands.add_content.not_allowed');
33572
- }
33573
- },
33574
-
33575
- execute: function() {
33576
- if (!widgetlist_field_element) {
33577
- widgetlist_field_element = widget_element.widget_field();
33578
- }
33579
-
33580
- scrivito.select_content().then(function(contents) {
33581
- var content = contents[0];
33582
- if (content) {
33583
- var widget_params = {
33584
- _obj_class: 'Scrivito::ContentWidget',
33585
- content: content
33586
- };
33587
-
33588
- scrivito.with_saving_overlay(
33589
- widgetlist_field_element.add_widget_via_create(widget_params, widget_element)
33590
- );
33591
- }
33592
- });
33593
- }
33594
- });
33595
- }
33596
- });
33597
- }());
33598
35140
  (function() {
33599
35141
  _.extend(scrivito, {
33600
35142
  add_subpage_command: function(child_list_element) {
@@ -33611,7 +35153,7 @@ var scrivito = {};
33611
35153
  return choose_obj_class.then(function(obj_class) {
33612
35154
  var add_subpage = child_list_element.create_child(obj_class);
33613
35155
  return scrivito.with_saving_overlay(add_subpage).then(function(obj) {
33614
- return scrivito.application_window.redirect_to('/' + obj.id());
35156
+ return scrivito.application_window.redirect_to(scrivito.path_for_id(obj.id()));
33615
35157
  });
33616
35158
  });
33617
35159
  }
@@ -33684,7 +35226,7 @@ var scrivito = {};
33684
35226
  execute: function() {
33685
35227
  var copy_page = scrivito.obj_clipboard.obj().copy_to(child_list_element.path());
33686
35228
  return scrivito.with_saving_overlay(copy_page).then(function(obj) {
33687
- return scrivito.application_window.redirect_to('/' + obj.id());
35229
+ return scrivito.application_window.redirect_to(scrivito.path_for_id(obj.id()));
33688
35230
  });
33689
35231
  }
33690
35232
  });
@@ -33768,7 +35310,7 @@ var scrivito = {};
33768
35310
  return choose_obj_class.then(function(obj_class) {
33769
35311
  var create_page = scrivito.obj.create({_obj_class: obj_class});
33770
35312
  return scrivito.with_saving_overlay(create_page).then(function(page) {
33771
- return scrivito.application_window.redirect_to('/' + page.id());
35313
+ return scrivito.application_window.redirect_to(scrivito.path_for_id(page.id()));
33772
35314
  });
33773
35315
  });
33774
35316
  }
@@ -33962,6 +35504,12 @@ var scrivito = {};
33962
35504
  title: scrivito.t('commands.delete_workspace.title'),
33963
35505
  icon: '&#xf018;',
33964
35506
 
35507
+ disabled: function() {
35508
+ if (!scrivito.user_permissions.can('delete_workspace')) {
35509
+ return scrivito.t('commands.delete_workspace.forbidden');
35510
+ }
35511
+ },
35512
+
33965
35513
  execute: function() {
33966
35514
  scrivito.confirmation_dialog({
33967
35515
  title: scrivito.t('commands.delete_workspace.dialog.title', workspace.title()),
@@ -34003,7 +35551,7 @@ var scrivito = {};
34003
35551
 
34004
35552
  execute: function() {
34005
35553
  return scrivito.with_saving_overlay(obj.duplicate()).then(function(obj) {
34006
- return scrivito.application_window.redirect_to('/' + obj.id());
35554
+ return scrivito.application_window.redirect_to(scrivito.path_for_id(obj.id()));
34007
35555
  });
34008
35556
  }
34009
35557
  });
@@ -34104,7 +35652,7 @@ var scrivito = {};
34104
35652
  return scrivito.details_dialog.open(obj.details_src(),
34105
35653
  scrivito.t(title_locale, obj.obj_class()));
34106
35654
  }, function() {
34107
- scrivito.application_window.redirect_to('/' + obj.id());
35655
+ scrivito.application_window.redirect_to(scrivito.path_for_id(obj.id()));
34108
35656
  });
34109
35657
  }
34110
35658
  });
@@ -34178,6 +35726,10 @@ var scrivito = {};
34178
35726
  tooltip: scrivito.t('commands.rebase_workspace.tooltip', workspace.title()),
34179
35727
 
34180
35728
  disabled: function() {
35729
+ if (!scrivito.user_permissions.can('rebase_workspace')) {
35730
+ return scrivito.t('commands.rebase_workspace.forbidden');
35731
+ }
35732
+
34181
35733
  if (!workspace.is_outdated()) {
34182
35734
  return scrivito.t('commands.rebase_workspace.uptodate', workspace.title());
34183
35735
  }
@@ -34216,6 +35768,12 @@ var scrivito = {};
34216
35768
  title: scrivito.t('commands.rename_workspace.title'),
34217
35769
  icon: '&#xf04f;',
34218
35770
 
35771
+ disabled: function() {
35772
+ if (!scrivito.user_permissions.can('rename_workspace')) {
35773
+ return scrivito.t('commands.rename_workspace.forbidden');
35774
+ }
35775
+ },
35776
+
34219
35777
  execute: function() {
34220
35778
  scrivito.prompt_dialog({
34221
35779
  title: scrivito.t('commands.rename_workspace.dialog.title', workspace.title()),
@@ -34626,12 +36184,18 @@ var scrivito = {};
34626
36184
  title: scrivito.t('commands.workspace_settings.title'),
34627
36185
  icon: '&#xf030;',
34628
36186
 
36187
+ disabled: function() {
36188
+ if (!scrivito.user_permissions.can('invite_to_workspace')) {
36189
+ return scrivito.t('commands.workspace_settings.forbidden');
36190
+ }
36191
+ },
36192
+
34629
36193
  execute: function() {
34630
36194
  var title = scrivito.t('commands.workspace_settings.dialog.title', workspace.title());
34631
36195
  scrivito.workspace_settings_dialog.open(title, workspace.memberships()).then(
34632
36196
  function(memberships) {
34633
36197
  scrivito.with_saving_overlay(
34634
- workspace.update({memberships: memberships}).then(function() {
36198
+ workspace.update_memberships(memberships).then(function() {
34635
36199
  return scrivito.reload();
34636
36200
  })
34637
36201
  );
@@ -34708,10 +36272,6 @@ var scrivito = {};
34708
36272
  widget_element.set_menu([
34709
36273
  scrivito.create_widget_command(widget_element),
34710
36274
  scrivito.choose_and_create_widget_command(widget_element),
34711
- //
34712
- // FIXME content-widget
34713
- //
34714
- // scrivito.add_content_command(widget_element),
34715
36275
  scrivito.widget_details_command(widget_element),
34716
36276
  create_command_separator(1),
34717
36277
  scrivito.save_widget_to_clipboard_command(widget_element),
@@ -34738,10 +36298,6 @@ var scrivito = {};
34738
36298
  widgetlist_field_element.set_menu([
34739
36299
  scrivito.create_widget_command(widgetlist_field_element),
34740
36300
  scrivito.choose_and_create_widget_command(widgetlist_field_element),
34741
- //
34742
- // FIXME content-widget
34743
- //
34744
- // scrivito.add_content_command(widgetlist_field_element),
34745
36301
  scrivito.copy_widget_from_clipboard_command(widgetlist_field_element)
34746
36302
  ].concat(widgetlist_field_element.menu()));
34747
36303
  });
@@ -34934,13 +36490,6 @@ var scrivito = {};
34934
36490
  activate();
34935
36491
  return false;
34936
36492
  });
34937
-
34938
- // TODO: remove this in 1.0.0.
34939
- scrivito.cms_document.local_jquery(jquery_object).on('scrivito_reload', function() {
34940
- scrivito.deprecation_warning('$.trigger("scrivito_reload")', '$.scrivito("reload")');
34941
- activate();
34942
- return false;
34943
- });
34944
36493
  };
34945
36494
  }());
34946
36495
  (function() {
@@ -35054,7 +36603,7 @@ var scrivito = {};
35054
36603
  dom_element.sortable({
35055
36604
  items: '> [data-scrivito-private-widget-id]',
35056
36605
  handle: '> .scrivito_editing_marker',
35057
- placeholder: 'scrivito_widget_drop_placeholder',
36606
+ placeholder: 'scrivito_widget_drop_placeholder scrivito_skip_widget_markup_validation',
35058
36607
  connectWith: '*[data-scrivito-field-type="widgetlist"]',
35059
36608
 
35060
36609
  start: scrivito.widget_sorting.start,
@@ -35511,6 +37060,637 @@ var scrivito = {};
35511
37060
  return data || {};
35512
37061
  };
35513
37062
  })();
37063
+ (function() {
37064
+ var focus;
37065
+ var focus_stack = [];
37066
+ var dragging;
37067
+
37068
+ // GEOMETRY UTILS
37069
+
37070
+ // distance between point and rectangle
37071
+ // returns 0 if point is inside rectangle
37072
+ var distance_point_rectangle = function(point, rect) {
37073
+ var clamped_x = Math.max(Math.min(point.x, rect.x + rect.width), rect.x);
37074
+ var clamped_y = Math.max(Math.min(point.y, rect.y + rect.height), rect.y);
37075
+
37076
+ var dist_x = point.x - clamped_x;
37077
+ var dist_y = point.y - clamped_y;
37078
+
37079
+ return Math.sqrt(dist_x * dist_x + dist_y * dist_y);
37080
+ };
37081
+
37082
+ var is_wrap_between = function(column, next_column) {
37083
+ var column_offset = column.offset();
37084
+ var next_column_offset = next_column.offset();
37085
+ var diff_x = next_column_offset.left - column_offset.left;
37086
+ var diff_y = next_column_offset.top - column_offset.top;
37087
+ return diff_y > diff_x;
37088
+ };
37089
+
37090
+ var is_container_wrapping = function(column_container) {
37091
+ return !!_.find(column_container.children(), function(column) {
37092
+ column = $(column);
37093
+ var next_column = column.next();
37094
+ if (next_column.length) {
37095
+ return is_wrap_between(column, next_column);
37096
+ }
37097
+ });
37098
+ };
37099
+
37100
+ // given a dom element, return it's bounding rectangle
37101
+ var bounding_rectangle = function(element) {
37102
+ element = $(element);
37103
+
37104
+ var offset = element.offset();
37105
+ var height;
37106
+
37107
+ var parent = element.parent();
37108
+
37109
+ if (element.is('[data-scrivito-widget-obj-class=ColumnWidget]') &&
37110
+ !is_container_wrapping(parent)) {
37111
+ // The column should occupy the entire available height unless its container is wrapping.
37112
+ height = parent.outerHeight();
37113
+ } else {
37114
+ height = element.outerHeight();
37115
+ }
37116
+
37117
+ return {
37118
+ x: offset.left,
37119
+ y: offset.top,
37120
+ width: element.outerWidth(),
37121
+ height: height
37122
+ };
37123
+ };
37124
+
37125
+ // which of the given dom elements is closest to the given point?
37126
+ var detect_closest = function(point, elements) {
37127
+ if (elements.length) {
37128
+ return _.min(elements, function(elem) {
37129
+ return distance_point_rectangle(point, bounding_rectangle(elem));
37130
+ });
37131
+ }
37132
+ };
37133
+
37134
+ // BOOTSTRAP UTILS
37135
+
37136
+ var create_row = function() {
37137
+ return $("<div class='row'></div>");
37138
+ };
37139
+
37140
+ // given an element, return it bootstrap column class, i.e. "col-md-6"
37141
+ var col_class = function(elem) {
37142
+ var classes = $(elem).attr("class").split(/\s+/);
37143
+
37144
+ return _.chain(classes).map(function(klass) {
37145
+ var match = /^col-md-[0-9]+/.exec(klass);
37146
+ return match ? match[0] : undefined;
37147
+ }).detect().value();
37148
+ };
37149
+
37150
+ var change_col_class = function(elem, new_class, animation) {
37151
+ animation = animation || 0;
37152
+
37153
+ var old_class_found;
37154
+
37155
+ _.each(_.range(1, 13), function(i) {
37156
+ var old_class = "col-md-" + i;
37157
+ if ($(elem).hasClass(old_class)) {
37158
+ old_class_found = true;
37159
+ if (old_class !== new_class) {
37160
+ $(elem).switchClass(old_class, new_class, animation);
37161
+ }
37162
+ }
37163
+ });
37164
+
37165
+ if (!old_class_found) {
37166
+ $(elem).addClass(new_class, animation);
37167
+ }
37168
+ };
37169
+
37170
+ var resize_row = function(row) {
37171
+ row = $(row);
37172
+
37173
+ var cols = row.children().toArray();
37174
+ var space = 12;
37175
+
37176
+ while (cols.length > 0) {
37177
+ var size = Math.round(space / cols.length);
37178
+ space -= size;
37179
+
37180
+ var col = cols.shift();
37181
+
37182
+ scrivito.change_col_class(col, "col-md-" + size, 100);
37183
+ }
37184
+ };
37185
+
37186
+ var garbage_collect = function(elem) {
37187
+ if ($(elem).attr("data-scrivito-widget-obj-class") === "ColumnWidget") {
37188
+ if ($(elem).children().length === 0) {
37189
+ // remove empty column
37190
+ var container = $(elem).parent();
37191
+ elem.remove();
37192
+
37193
+ var leftover_columns = $(container).children();
37194
+ if (leftover_columns.length > 1) {
37195
+ resize_row(container);
37196
+ }
37197
+ else {
37198
+ // unwrap last column
37199
+ var last_column = leftover_columns[0];
37200
+ var widgets_to_unwrap = $(last_column).children();
37201
+
37202
+ if (widgets_to_unwrap.length === 0) {
37203
+ // last column is empty.
37204
+ // this should never happen, but better safe than sorry...
37205
+ $(container).remove();
37206
+ }
37207
+ else {
37208
+ // remove column widget
37209
+ $(widgets_to_unwrap).unwrap();
37210
+ // remove column container widget
37211
+ $(widgets_to_unwrap).unwrap();
37212
+ }
37213
+ }
37214
+ }
37215
+ }
37216
+ };
37217
+
37218
+ // FOCUS MARKER
37219
+
37220
+ var focus_marker = function() {
37221
+ var focus_marker;
37222
+
37223
+ var rects;
37224
+
37225
+ var show_rectangle = function(num, x1, y1, x2, y2) {
37226
+ var rect = $(rects[num]);
37227
+
37228
+ rect.offset({left: x1, top: y1});
37229
+ rect.width(x2 - x1);
37230
+ rect.height(y2 - y1);
37231
+
37232
+ rect.show();
37233
+ };
37234
+
37235
+ return {
37236
+ init: function() {
37237
+ rects = _.map(_.range(4), function() {
37238
+ var rect = $("<div class='focus_marker'></div>");
37239
+ rect.css("pointer-events", "none");
37240
+ rect.css("background", "rgba(255, 159, 0, 0.25)");
37241
+ rect.css("position", "absolute");
37242
+ rect.hide();
37243
+
37244
+ $("body").append(rect);
37245
+
37246
+ return rect;
37247
+ });
37248
+ },
37249
+
37250
+ show: function(focus) {
37251
+ var offset = scrivito.cms_document.offset(focus)
37252
+ var bounds = bounding_rectangle(focus);
37253
+ var width = bounds.width;
37254
+ var height = bounds.height;
37255
+
37256
+ // FIXME, use actual values
37257
+ var window_bottom = 2048;
37258
+ var window_right = 2048;
37259
+
37260
+ show_rectangle(0, 0, 0, offset.left, window_bottom);
37261
+ show_rectangle(1, offset.left + width, 0, window_right, window_bottom);
37262
+
37263
+ show_rectangle(2, offset.left, 0, offset.left + width, offset.top);
37264
+ show_rectangle(3, offset.left, offset.top + height, offset.left + width, window_bottom);
37265
+ },
37266
+
37267
+ hide: function() {
37268
+ _.each(rects, function(rect) { $(rect).hide(); });
37269
+ }
37270
+ };
37271
+ }();
37272
+
37273
+ var find_selectable_targets = function(root) {
37274
+ root = $(root);
37275
+
37276
+ if (root.is('[data-scrivito-widget-obj-class=ColumnWidget]')) {
37277
+ return root.children();
37278
+ }
37279
+
37280
+ var widgetlists = root.find('[data-scrivito-field-type=widgetlist]')
37281
+ .addBack('[data-scrivito-field-type=widgetlist]');
37282
+ widgetlists = _.reject(widgetlists, function(widgetlist) {
37283
+ // Reject if not a top-level widgetlist.
37284
+ var wrapping_widgetlist = $(widgetlist).parent()
37285
+ .closest('[data-scrivito-field-type=widgetlist]').get(0);
37286
+ return wrapping_widgetlist && $.contains(root.get(0), wrapping_widgetlist);
37287
+ });
37288
+
37289
+ var selectable_targets = [];
37290
+ _.each(widgetlists, function(widgetlist) {
37291
+ var widgets = $(widgetlist).children();
37292
+ if (widgets.length) {
37293
+ selectable_targets = selectable_targets.concat(widgets.toArray());
37294
+ } else {
37295
+ selectable_targets.push(widgetlist);
37296
+ }
37297
+ });
37298
+
37299
+ return selectable_targets;
37300
+ };
37301
+
37302
+ var find_gesture_targets = function(mouse, focus) {
37303
+ var selectable_targets = find_selectable_targets(focus);
37304
+ var target_row = detect_closest(mouse, selectable_targets);
37305
+ var target;
37306
+
37307
+ if ($(target_row).is("[data-scrivito-widget-obj-class=ColumnContainerWidget]")) {
37308
+ target = detect_closest(mouse, $(target_row).children());
37309
+ } else {
37310
+ target = target_row;
37311
+ }
37312
+
37313
+ return {
37314
+ target_row: target_row,
37315
+ target: target
37316
+ };
37317
+ };
37318
+
37319
+ var detect_gesture = function(mouse, target, target_row) {
37320
+ if ($(target).is('[data-scrivito-field-type=widgetlist]')) {
37321
+ return {
37322
+ name: 'row_insert'
37323
+ };
37324
+ }
37325
+
37326
+ target_row = $(target_row);
37327
+ var rowY = target_row.offset().top;
37328
+ var rowHeight = target_row.height();
37329
+
37330
+ var targetY = $(target).offset().top;
37331
+ var targetHeight = $(target).height();
37332
+
37333
+ var event_row_y = (mouse.y - rowY) / rowHeight;
37334
+ var event_target_y_abs = mouse.y - targetY;
37335
+ var event_target_y = event_target_y_abs / targetHeight;
37336
+
37337
+ var is_row_insert_before = event_row_y < (1 / 4) && event_target_y < (1 /4) &&
37338
+ event_target_y_abs < 20;
37339
+ var is_row_insert_after = event_row_y > (3 / 4) && event_target_y > (3 /4) &&
37340
+ event_target_y_abs > (targetHeight - 20);
37341
+
37342
+ if (is_row_insert_before || is_row_insert_after) {
37343
+ return {
37344
+ name: 'row_insert',
37345
+ before: is_row_insert_before
37346
+ };
37347
+ } else {
37348
+ var targetX = $(target).offset().left;
37349
+ var targetWidth = $(target).width();
37350
+ var event_target_x_abs = mouse.x - targetX;
37351
+ var eventX = event_target_x_abs / targetWidth;
37352
+
37353
+ var widget_obj_class = $(target).attr("data-scrivito-widget-obj-class");
37354
+ var contains_widgetlist = !!$(target).find('[data-scrivito-field-type=widgetlist]').length;
37355
+ var is_applicable_for_insert_inside = (contains_widgetlist || widget_obj_class === 'ColumnWidget') &&
37356
+ dragging !== target;
37357
+
37358
+ var is_col_insert_before = eventX < (1 / 4) && event_target_x_abs < 20;
37359
+ var is_col_insert_after = eventX > (3 / 4) && event_target_x_abs > (targetWidth - 20);
37360
+ var distance = distance_point_rectangle(mouse, bounding_rectangle(target));
37361
+ if (is_applicable_for_insert_inside && !is_col_insert_before && !is_col_insert_after && distance < 20) {
37362
+ return {
37363
+ name: 'insert_inside',
37364
+ before: event_target_y < (1 / 2)
37365
+ };
37366
+ } else {
37367
+ return {
37368
+ name: 'col_insert',
37369
+ before: eventX < 0.5
37370
+ };
37371
+ }
37372
+ }
37373
+ };
37374
+
37375
+ var loose_focus = function(mouse, focus) {
37376
+ if (focus) {
37377
+ var distance = distance_point_rectangle(mouse, bounding_rectangle(focus));
37378
+ if (distance > 20) {
37379
+ return focus_stack.pop();
37380
+ } else {
37381
+ var targets = find_gesture_targets(mouse, _.last(focus_stack) || $(focus).closest('body'));
37382
+ if (targets.target && targets.target !== focus) {
37383
+ return focus_stack.pop();
37384
+ }
37385
+ }
37386
+ }
37387
+
37388
+ return focus;
37389
+ };
37390
+
37391
+ var offset_center = function(element, element_offset, next_element, next_element_offset) {
37392
+ var left_boundary = element_offset.left + element.outerWidth();
37393
+ var right_boundary = next_element_offset.left;
37394
+ var horizontal_offset = (right_boundary - left_boundary) / 2
37395
+ var left = left_boundary + horizontal_offset;
37396
+
37397
+ var top_boundary = element_offset.top + element.outerHeight();
37398
+ var bottom_boundary = next_element_offset.top;
37399
+ var vertical_offset = (bottom_boundary - top_boundary) / 2
37400
+ var top = top_boundary + vertical_offset;
37401
+
37402
+ return {left: left, top: top};
37403
+ };
37404
+
37405
+ _.extend(scrivito, {
37406
+ change_col_class: change_col_class,
37407
+
37408
+ drag_n_drool: {
37409
+ init: function() {
37410
+ var hidden;
37411
+
37412
+ var cursor = $('<div class="scrivito_dnd_cursor"></div>');
37413
+ cursor.hide();
37414
+ $("body").append(cursor);
37415
+
37416
+ focus_marker.init();
37417
+
37418
+ var insert_at;
37419
+ var insert_type;
37420
+ var insert_before;
37421
+
37422
+ scrivito.gui.on('document', function(document) {
37423
+ var body = document.dom_element().find("body");
37424
+
37425
+ body.on("dragover", function(e) {
37426
+ e.originalEvent.dataTransfer.dropEffect = 'move';
37427
+
37428
+ if (e.preventDefault) {
37429
+ e.preventDefault(); // Necessary. Allows us to drop.
37430
+ }
37431
+
37432
+
37433
+ // REPLACE ORIGINAL WITH PLACEHOLDER
37434
+ if (!hidden) {
37435
+ $(dragging).css("opacity", "0.5");
37436
+ hidden = true;
37437
+ }
37438
+
37439
+ // using originalEvent as a workaround,
37440
+ // see https://github.com/jquery/jquery/issues/1925
37441
+ var mouse = {x: e.originalEvent.pageX, y: e.originalEvent.pageY}
37442
+
37443
+ focus = loose_focus(mouse, focus);
37444
+
37445
+ if (focus) {
37446
+ focus_marker.show(focus);
37447
+ }
37448
+ else {
37449
+ focus_marker.hide();
37450
+ }
37451
+
37452
+ var targets = find_gesture_targets(mouse, focus || body);
37453
+ var target_row = $(targets.target_row);
37454
+ var target = targets.target;
37455
+
37456
+ // This should NEVER happen!
37457
+ if (!target) {
37458
+ console.error('Missing target!');
37459
+ return;
37460
+ }
37461
+
37462
+ var gesture = detect_gesture(mouse, target, target_row);
37463
+
37464
+ // TODO take widget into account: if small widget,
37465
+ // only upper 1/3 of widget should count as "row"
37466
+ if (gesture.name === 'row_insert') {
37467
+ var before = gesture.before;
37468
+
37469
+ // CURSOR
37470
+ cursor.height("0px");
37471
+ cursor.width(target_row.parent().outerWidth());
37472
+
37473
+ // TODO update Cursor position on scroll
37474
+ // FIXME: why that - offset.top -= 0.5 * cursor.outerHeight();
37475
+
37476
+ var offset = scrivito.cms_document.offset(target_row);
37477
+
37478
+ if (before) {
37479
+ var prev_row = target_row.prev();
37480
+ if (prev_row.length) {
37481
+ var prev_row_offset = scrivito.cms_document.offset(prev_row);
37482
+ offset.top = offset_center(prev_row, prev_row_offset, target_row, offset).top;
37483
+ }
37484
+ } else {
37485
+ var next_row = target_row.next();
37486
+ if (next_row.length) {
37487
+ var next_row_offset = scrivito.cms_document.offset(next_row);
37488
+ offset.top = offset_center(target_row, offset, next_row, next_row_offset).top;
37489
+ } else {
37490
+ offset.top += target_row.outerHeight();
37491
+ }
37492
+ }
37493
+
37494
+ offset.left = scrivito.cms_document.offset(target_row.parent()).left;
37495
+ cursor.offset(offset);
37496
+ cursor.show();
37497
+
37498
+ // REMEMBER
37499
+ insert_at = target_row;
37500
+ insert_type = "row";
37501
+ insert_before = before;
37502
+ } else if (gesture.name === 'insert_inside') {
37503
+ // CURSOR
37504
+
37505
+ var bounds = bounding_rectangle(target);
37506
+ cursor.width(bounds.width);
37507
+ cursor.height(bounds.height);
37508
+
37509
+ // TODO update Cursor position on scroll
37510
+ var offset = scrivito.cms_document.offset(target);
37511
+ cursor.offset(offset);
37512
+ cursor.show();
37513
+
37514
+ if (insert_at === target && insert_type === "inside") {
37515
+ var focus_time = (new Date()) - focus_since;
37516
+
37517
+ if (focus_time > 500) {
37518
+ if (focus) {
37519
+ focus_stack.push(focus);
37520
+ }
37521
+ focus = target;
37522
+ focus_since = undefined;
37523
+ }
37524
+ } else {
37525
+ focus_since = new Date();
37526
+ // REMEMBER
37527
+ insert_at = target;
37528
+ insert_type = "inside";
37529
+ }
37530
+
37531
+ insert_before = gesture.before;
37532
+ } else if (gesture.name === 'col_insert') {
37533
+ var before = gesture.before;
37534
+
37535
+ // CURSOR
37536
+ cursor.height($(target).outerHeight());
37537
+ cursor.width("0px");
37538
+
37539
+ // TODO update Cursor position on scroll
37540
+ var offset = scrivito.cms_document.offset(target);
37541
+ var target_jq = $(target);
37542
+
37543
+ if (before) {
37544
+ var prev_column = target_jq.prev();
37545
+ if (prev_column.length && !is_wrap_between(prev_column, target_jq)) {
37546
+ offset.left = offset_center(prev_column, scrivito.cms_document.offset(prev_column),
37547
+ target_jq, offset).left;
37548
+ cursor.height(target_jq.parent().outerHeight());
37549
+ }
37550
+ } else {
37551
+ var next_column = target_jq.next();
37552
+ if (next_column.length && !is_wrap_between(target_jq, next_column)) {
37553
+ offset.left = offset_center(target_jq, offset, next_column,
37554
+ scrivito.cms_document.offset(next_column)).left;
37555
+ cursor.height(target_jq.parent().outerHeight());
37556
+ } else {
37557
+ offset.left += target_jq.outerWidth();
37558
+ }
37559
+ }
37560
+
37561
+ cursor.offset(offset);
37562
+ cursor.show();
37563
+
37564
+ // REMEMBER
37565
+ insert_at = target;
37566
+ insert_type = "col";
37567
+ insert_before = before;
37568
+ } else {
37569
+ $.error('Unknown gesture: ' + gesture);
37570
+ }
37571
+ });
37572
+
37573
+ });
37574
+
37575
+ scrivito.on('content', function(root_element) {
37576
+ var widget_lists = $(root_element).find("[data-scrivito-field-type=widgetlist]");
37577
+
37578
+ var widgets = widget_lists.children();
37579
+
37580
+ var handles = widgets.find("> .scrivito_editing_marker");
37581
+
37582
+ handles.attr("draggable", "true");
37583
+
37584
+ handles.on("dragstart", function(e) {
37585
+ e.originalEvent.dataTransfer.effectAllowed = 'move';
37586
+
37587
+ // Is required in order to dragover event is triggered in FF and Safari.
37588
+ // http://stackoverflow.com/questions/21507189/dragenter-dragover-and-drop-events-not-working-in-firefox
37589
+ // IE 11 however does not allow to set the data, which results in a security exception.
37590
+ try {
37591
+ e.originalEvent.dataTransfer.setData('text/plain', e.originalEvent.target.id);
37592
+ } catch(error) {}
37593
+
37594
+ //var dragIcon = document.createElement('img');
37595
+ //// TODO use real logo
37596
+ //dragIcon.src = 'logo.png';
37597
+ //dragIcon.width = 100;
37598
+ //e.originalEvent.dataTransfer.setDragImage(dragIcon, -10, -10);
37599
+
37600
+ dragging = $(this).parent()[0];
37601
+ // FIXME: Find also the structure widget.
37602
+ focus = $(dragging).closest("[data-scrivito-widget-obj-class=ColumnWidget]")[0];
37603
+
37604
+ if ($(focus).children().length === 1) { // TODO: Only for ColumnContainerWidget
37605
+ // if dragging the only widget inside a column
37606
+ // focussing that column does not make sense
37607
+ focus = $(focus).parent().
37608
+ closest("[data-scrivito-widget-obj-class=ColumnWidget]")[0];
37609
+ }
37610
+
37611
+ hidden = false;
37612
+ });
37613
+
37614
+ handles.on("dragend", function(e) {
37615
+
37616
+ if (window.debugdrag) { return }
37617
+
37618
+ if (insert_at == dragging) {
37619
+ // dragged a widget on itself - do nothing
37620
+ $(dragging).css("opacity", "1");
37621
+ }
37622
+ else if (insert_at) {
37623
+ var old_parent = $(dragging).parent();
37624
+
37625
+ if (insert_type == "inside") {
37626
+ // TODO do noting if not ColumnContainerWidget
37627
+ // INSIDE EXISTING COLUMN
37628
+ $(dragging).hide();
37629
+ $(insert_at)[insert_before ? "prepend" : "append"](dragging);
37630
+ $(dragging).slideDown(100);
37631
+
37632
+ $(dragging).css("opacity", "1");
37633
+
37634
+ garbage_collect(old_parent);
37635
+ }
37636
+ else if (insert_type == "row") {
37637
+ // ROW INSERT
37638
+ $(dragging).hide();
37639
+
37640
+ if (insert_before === undefined) {
37641
+ $(insert_at).append(dragging);
37642
+ } else {
37643
+ $(insert_at)[insert_before ? "before" : "after"](dragging);
37644
+ }
37645
+ $(dragging).css("opacity", "1");
37646
+
37647
+ $(dragging).slideDown(100);
37648
+
37649
+ garbage_collect(old_parent);
37650
+ }
37651
+ else {
37652
+ // COL INSERT
37653
+ var insert_at_obj_class = $(insert_at).attr("data-scrivito-widget-obj-class");
37654
+ if (insert_at_obj_class !== "ColumnWidget") {
37655
+ $(insert_at).wrap(
37656
+ "<div class='row' data-scrivito-widget-obj-class=ColumnContainerWidget>" +
37657
+ "<div class='col-md-12' data-scrivito-widget-obj-class=ColumnWidget></div>" +
37658
+ "</div>");
37659
+
37660
+ insert_at = $(insert_at).parent();
37661
+ }
37662
+
37663
+ $(dragging).detach();
37664
+ $(dragging).wrap("<div class='col-md-12' data-scrivito-widget-obj-class=ColumnWidget></div>");
37665
+ var insert_column = $(dragging).parent();
37666
+
37667
+ $(insert_at)[insert_before ? "before" : "after"](insert_column);
37668
+
37669
+ $(dragging).css("opacity", "1");
37670
+ $(dragging).show(100);
37671
+
37672
+ // collect old parent before resizing,
37673
+ // since it could be inside the same row
37674
+ garbage_collect(old_parent);
37675
+
37676
+ resize_row($(insert_at).closest(".row"));
37677
+ }
37678
+ }
37679
+
37680
+ cursor.hide();
37681
+ focus_marker.hide();
37682
+
37683
+ return false;
37684
+ });
37685
+ });
37686
+ }
37687
+ }
37688
+ });
37689
+ }());
37690
+
37691
+
37692
+
37693
+
35514
37694
 
35515
37695
 
35516
37696
 
@@ -35614,6 +37794,7 @@ var scrivito = {};
35614
37794
 
35615
37795
 
35616
37796
 
37797
+
35617
37798
  //
35618
37799
 
35619
37800