Browse files

Merge branch 'integration'

  • Loading branch information...
2 parents 611bbc8 + e00e548 commit 89abf0a8adfc3219b778b4a38f74690d252b9cbe @brendo committed Feb 3, 2012
Showing with 145 additions and 94 deletions.
  1. +4 −4 README.md
  2. +131 −86 assets/scaffolds.sections.js
  3. +2 −2 extension.driver.php
  4. +8 −2 extension.meta.xml
View
8 README.md
@@ -2,9 +2,9 @@
Scaffolds allows you to quickly create Sections from a file. Section definitions can be exported and then imported into other Symphony installations using JSON. Definitions can be saved and reused on other Symphony projects to save you time recreating those common sections.
-- Version: 0.4
-- Date: 10th August, 2011
-- Requirements: Symphony 2.2 or newer, <http://github.com/symphonycms/symphony-2/>, a browser that supports the [FileReader API](https://developer.mozilla.org/en/DOM/FileReader)
+- Version: 0.5
+- Date: 3rd February, 2011
+- Requirements: Symphony 2.2 or newer, <http://github.com/symphonycms/symphony-2/>, a [browser that supports](http://caniuse.com/#feat=filereader) the [FileReader API](https://developer.mozilla.org/en/DOM/FileReader)
- Author: Brendan Abbott, brendan@bloodbone.ws
- GitHub Repository: <http://github.com/brendo/scaffolds>
@@ -18,7 +18,7 @@ For further information, please refer to the [wiki](https://github.com/brendo/sc
## Notes
-* This extension makes use of the [FileReader API](https://developer.mozilla.org/en/DOM/FileReader) to parse the files without actually uploading them a destination. At the time of release, this is only supported by Firefox and Chrome.
+* This extension makes use of the [FileReader API](https://developer.mozilla.org/en/DOM/FileReader) to parse the files without actually uploading them a destination. At the time of release, this is supported by Firefox 3.6+, Chrome 7+ and IE10+. A Safari nightly also has support for the `FileReader API`. Check the latest support at [caniuse.com](http://caniuse.com/#feat=filereader)
* The only valid file that can be parsed at the moment is JSON, with the file extension of `.json`.
* Checkbox values accept 'yes' and 'no' for 'checked' or 'unchecked', just like Symphony.
View
217 assets/scaffolds.sections.js
@@ -7,7 +7,8 @@
});
var $scaffolds = $('#scaffolds-area'),
- $fields = $('#fields-duplicator');
+ $fields = $('#fields-duplicator'),
+ $sectionEssentials = $scaffolds.next('fieldset.settings');
// Add a dummy upload field so we can use the FileReader API
// Add a dummy iframe so that when exporting the definition
@@ -29,10 +30,10 @@
$scaffolds.find('ul').delegate('a', 'click', function(event) {
var $self = $(this);
- if($self.data('action') == 'import') {
+ if($self.data('action') === 'import') {
$file.trigger('click');
}
- else if($self.data('action') == 'export') {
+ else if($self.data('action') === 'export') {
Scaffolds.export();
}
@@ -74,7 +75,7 @@
Scaffolds.applyMessage();
Scaffolds.closeDropDown();
}
- }
+ };
// If the file isn't one of our valid types, abort.
if(Scaffolds.acceptedFiles.test(files[0].name)) {
@@ -97,31 +98,54 @@
// Section Editor duplicator
import: function(def) {
var $controls = $fields.find('.controls'),
- imported = 0;
+ imported = 0,
+ fields_definition = {},
+ section_definition = {};
+
+ // New versions of Scaffolds have section and field objects.
+ // Old ones just output the fields.
+ if(def.fields !== undefined && def.section !== undefined) {
+ section_definition = def.section;
+ fields_definition = def.fields;
+ }
+ else {
+ fields_definition = def;
+ }
- // Loop over the definition and trigger the duplicators
- for(var label in def) {
- if(!def.hasOwnProperty(label)) continue;
+ // Loop over section definition
+ for(var setting in section_definition) {
+ if(!section_definition.hasOwnProperty(setting)) continue;
+
+ Scaffolds.set(
+ $sectionEssentials.find(':input[name*=' + setting + ']').closest('label'),
+ setting,
+ section_definition[setting]
+ );
+ }
+
+ // Loop over the fields definition and trigger the duplicators
+ for(var label in fields_definition) {
+ if(!fields_definition.hasOwnProperty(label)) continue;
+ var definition = fields_definition[label];
- var definition = def[label];
// Check to make sure we aren't overriding an existing field
// definition with the same name
if(
$fields.find('li.instance input[name*=label]').filter(function() {
- return $(this).val() == label;
+ return $(this).val() === label;
}).length !== 1
) {
$controls.find('option[data-type = ' + definition.type + ']').attr('selected', 'selected');
$controls.find('a.constructor').trigger('click');
- var field = $fields.find('li.instance:last-of-type div.content');
- field.find('input[name*=label]').val(label);
+ var $field = $fields.find('li.instance:last-of-type div.content');
+ $field.find('input[name*=label]').val(label);
// Loop over our 'el' and set the values
for(var k in definition) {
if(!definition.hasOwnProperty(k) || k === 'type') continue;
- Scaffolds.set(field, k, definition[k]);
+ Scaffolds.set($field, k, definition[k]);
}
imported++;
@@ -141,76 +165,50 @@
// This iterates over all the instances and generates a JSON schema
// for the user to download. The JSON filename is the Section handle.
export: function() {
- var def = {};
+ var def = {
+ section: {},
+ fields: {}
+ };
+
+ // Export the Section metadata
+ $sectionEssentials.find('input:not(:hidden)').each(function() {
+ var $setting = $(this),
+ label = $setting.attr('name').replace(/(meta\[|\])/g, ''),
+ data = Scaffolds.get($setting);
+
+ if(data !== false) def.section[label] = data;
+ });
+ // Export the Fields
$fields.find('li.instance div.content').each(function() {
var $field = $(this),
schema = {},
- label;
+ // The key for def needs to the value of 'Label'
+ label = $field.find('input[name*=label]').val();
- // The key for def needs to the value of 'Label'
- label = $field.find('input[name*=label]').val();
-
- if(label == "") return;
+ if(label === "") return;
// Get the type for this field instance
- schema['type'] = $field.find('input[name*=type]:hidden').val();
+ schema.type = $field.find('input[name*=type]:hidden').val();
// Parse the rest as usual I guess
- $field.find(':input').filter(':not(:hidden), ').each(function() {
+ $field.find(':input').filter(':not(:hidden)').each(function() {
var $instance = $(this),
// For each of the fields in the setting, we need to serialize
// the field information, then convert it to the JSON format
// we are expecting..
- name = $instance.attr('name').match(/\[([a-z_]+)\](\[\])?$/),
- value = $instance.val();
+ name = $instance.attr('name').match(/\[([a-z_]+)\](\[\])?$/);
// Get fields that have a name, aren't the label (we already got that)
// and have a field that actually has a value.
- if(name.length >= 2 && name[1] !== 'label' && value !== '') {
- // Custom logic for Checkbox
- if($instance.is(':checkbox')) {
- schema[name[1]] = ($instance.is(':checked')) ? 'yes' : 'no';
- }
+ if(name.length >= 2 && name[1] !== 'label' && $instance.val() !== '') {
+ var data = Scaffolds.get($instance);
- // Custom logic for Select Box
- else if($instance.is('select')) {
- var $selected = $instance.find('option:selected'),
- tmp = [];
-
- for(var i = 0, l = $selected.length; i < l; i++) {
- var $v = $($selected[i]);
-
- // If `v` is a number, we'll assume that's referencing an ID
- // This isn't useful to export across environments, but exporting
- // the Name might be
- if($v.val().search(/^[0-9]+$/) !== -1) {
- var t = {
- 'value': $v.text()
- };
-
- if($v.closest('optgroup').length) {
- t.optgroup = $v.closest('optgroup').attr('label');
- }
- tmp.push(t);
- }
- // It's fine, normal Select Box value
- else {
- tmp.push({'value': $v.val()});
- }
- }
-
- schema[name[1]] = tmp;
- }
-
- // jQuery's val() will handle alot of the suck for us
- else {
- schema[name[1]] = value;
- }
+ if(data !== false) schema[name[1]] = data;
}
});
- def[label] = schema;
+ def.fields[label] = schema;
});
Scaffolds.closeDropDown();
@@ -224,66 +222,113 @@
);
},
+ // Returns the value of a given field, approtiate for Symphony.
+ get: function($field) {
+ // Custom logic for Checkbox
+ if($field.is(':checkbox')) {
+ return $field.is(':checked') ? 'yes' : 'no';
+ }
+
+ // Custom logic for Select Box
+ else if($field.is('select')) {
+ var $selected = $field.find('option:selected'),
+ tmp = [];
+
+ for(var i = 0, l = $selected.length; i < l; i++) {
+ var $v = $($selected[i]);
+
+ // If `v` is a number, we'll assume that's referencing an ID
+ // This isn't useful to export across environments, but exporting
+ // the Name might be
+ if($v.val().search(/^[0-9]+$/) !== -1) {
+ var t = {
+ 'value': $v.text()
+ };
+
+ if($v.closest('optgroup').length) {
+ t.optgroup = $v.closest('optgroup').attr('label');
+ }
+ tmp.push(t);
+ }
+ // It's fine, normal Select Box value
+ else {
+ tmp.push({'value': $v.val()});
+ }
+ }
+
+ return tmp;
+ }
+
+ // jQuery's val() will handle alot of the suck for us
+ else {
+ return $field.val();
+ }
+ },
+
// Given the field context and a key/value pair, this will set the
// approtiate values in the Field's settings.
set: function(field, key, value) {
- var field = field.find(':input[name*=' + key + ']');
+ var $field = field.find(':input[name*=' + key + ']');
+
+ if($field.length === 0) return false;
// Select
- if(field.is('select')) {
+ if($field.is('select')) {
if($.isArray(value)) {
for(var i = 0, l = value.length; i < l; i++) {
var v = value[i];
// Select has optgroup
- if(field.find('optgroup').length) {
- field
- .find('optgroup[label = ' + v.optgroup + ']')
- .find('option').filter(function() {
- return $(this).text() == v.value;
- })
- .attr('selected', 'selected');
+ if($field.find('optgroup').length) {
+ Scaffolds.setSelectBox(
+ $field.find('optgroup[label = ' + v.optgroup + ']'),
+ v.value
+ );
}
// Select doesn't have an optgroup
else {
- field
- .find('option').filter(function() {
- return $(this).text() == v.value;
- })
- .attr('selected', 'selected');
+ Scaffolds.setSelectBox($field, v.value);
}
}
}
else {
- field.find('option[value=' + value + ']').attr('selected', 'selected');
+ Scaffolds.setSelectBox($field, value);
}
-
- return;
}
// Checkbox
// Symphony adds a hidden field before a checkbox, so field
// may be an area with two elements. The first element will be a
// hidden field, the second will be a checkbox.
- if(
- field.length == 2 && $(field[1]).is(':checkbox')
+ else if(
+ $field.length === 2 && $field.eq(1).is(':checkbox')
) {
- $(field[1]).attr('checked', (value !== 'no'));
+ $field.eq(1).attr('checked', (value !== 'no'));
}
// Not all Checkbox fields have the hidden field, so handle that
// case as well
- else if(field.is(':checkbox')) {
- field.attr('checked', (value !== 'no'));
+ else if($field.is(':checkbox')) {
+ $field.attr('checked', (value !== 'no'));
}
// Input
else {
- field.val(value);
+ $field.val(value);
}
},
+ // Given an element (<select> or <optgroup>) and a value, this will search
+ // all the options and add the selected attribute where the option's
+ // text() or @value matches the given value.
+ setSelectBox: function(el, value) {
+ return el.find('option').filter(function() {
+ var $option = $(this);
+ return $option.text() === value || $option.attr('value') === value;
+ }).attr('selected', 'selected');
+ },
+
// Removes the toggle class. Can be done with :target selector,
// but we don't want the 'snap to element' effect, so no bingo.
closeDropDown: function() {
View
4 extension.driver.php
@@ -5,8 +5,8 @@
public function about() {
return array(
'name' => 'Scaffolds',
- 'version' => '0.4',
- 'release-date' => '2011-08-10',
+ 'version' => '0.5',
+ 'release-date' => '2012-02-03',
'author' => array(
'name' => 'Brendan Abbott',
'email' => 'brendan@bloodbone.ws'
View
10 extension.meta.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<extension id="scaffolds">
+<extension id="scaffolds" status="released" xmlns="http://symphony-cms.com/schemas/extension/1.0">
<name>Scaffolds</name>
- <description>A Symphony extension that allows a developer to quickly create Sections using JSON</description>
+ <description lang="en">A Symphony extension that allows a developer to quickly create Sections using JSON</description>
<repo type="github">https://github.com/brendo/scaffolds</repo>
<url type="discuss">http://symphony-cms.com/discuss/thread/74663/</url>
<types>
@@ -14,6 +14,12 @@
</author>
</authors>
<releases>
+ <release version="0.5" date="2012-02-03" min="2.2">
+ - Add support for exporting/importing the Section essentials (name, navigation group, backend visibility). Definition files now have a slightly different output format (old formats still supported). Implements [#4](https://github.com/brendo/scaffolds/issues/4) &amp; [#5](https://github.com/brendo/scaffolds/issues/5)
+ - Fixed exporting of some Select values, [#2](https://github.com/brendo/scaffolds/issues/2)
+ - Exported definitions are now pretty printed
+ - Small Javascript cleanup
+ </release>
<release version="0.4" date="2011-08-10" min="2.2" />
</releases>
</extension>

0 comments on commit 89abf0a

Please sign in to comment.