Skip to content
This repository

[Property View] Fix bug: Add/Remove SelectMenu option refresh issue. #275

Open
wants to merge 1 commit into from

2 participants

X.Q. Kuang Geoff Gustafson
X.Q. Kuang

No description provided.

X.Q. Kuang

@zhizhangchen The code updated.

  1. Fixed add/remove refresh in layoutView and codeView issue.
  2. Make ID of select menu table flexible, previous implementation is fixed to 'selectOption'.

Problems:
1. Focus lost after change text/value.
2. Current implementation is redraw whole table to refresh, the performance a bit slower than operate element directly.

Please see the code for more information.

Geoff Gustafson
Collaborator

Fixed up the minor issues and merged to stable branch for the moment at least. I'll decide later today whether i'm merging that into master (reverting event handlers) or what.

Geoff Gustafson
Collaborator

Merged into master.

Geoff Gustafson grgustaf closed this August 31, 2012
Geoff Gustafson grgustaf reopened this August 31, 2012
Geoff Gustafson
Collaborator

I'll reopen just for Shane to see a little history. Also, please have Shane look at the comment history from the previous lists PR so he can see the kind of thought and bug fixing that went in before we finally merged it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Aug 31, 2012
[Property View] Fix bug: Add/Remove SelectMenu option refresh issue. 5512373
This page is out of date. Refresh to see the latest.
2  src/css/builder.css
@@ -929,7 +929,7 @@ div.propertyItems > div > * {
929 929
     display: table-cell;
930 930
     padding-bottom: 8px;
931 931
 }
932  
-table#selectOption {
  932
+table.selectTable {
933 933
     width: 100%;
934 934
 }
935 935
 div.propertyItems label[for] {
385  src/js/views/property.js
@@ -85,35 +85,73 @@
85 85
             widget.refresh(event,widget);
86 86
         },
87 87
 
88  
-        _setProperty: function(property, value) {
89  
-            var viewId = property + '-value';
90  
-            if (typeof(value) === 'boolean') {
91  
-                this.element.find("#" + viewId).attr('checked', value);
92  
-            } else {
93  
-                this.element.find("#" + viewId).val(value);
  88
+        _setProperty: function(property, propType, value) {
  89
+            var element = this.element.find("#" + property + '-value');
  90
+            switch (propType) {
  91
+                case "boolean":
  92
+                    element.attr('checked', value);
  93
+                    break;
  94
+                default:
  95
+                    element.val(value);
94 96
             }
95 97
         },
96 98
 
  99
+        _redrawProperty: function(property, newElment) {
  100
+            var element = this.element.find("#" + property + '-value');
  101
+            element.replaceWith(newElment);
  102
+        },
  103
+
97 104
         _modelUpdatedHandler: function(event, widget) {
98  
-            var affectedWidget, id, value;
  105
+            var affectedWidget, id, value, propType;
99 106
             widget = widget || this;
100 107
             if (event && event.type === "propertyChanged") {
101 108
                 if (event.node.getType() !== 'Design') {
102 109
                     id = event.property + '-value';
103 110
                     affectedWidget = widget.element.find('#' + id);
104  
-                    if (affectedWidget.attr('type') !== 'checkbox') {
105  
-                        value = affectedWidget.val();
106  
-                    } else {
107  
-                        value = affectedWidget.attr('checked')?true:false;
  111
+                    propType = BWidget.getPropertyType(event.node.getType(), event.property);
  112
+
  113
+                    // Get value to for commparation
  114
+                    switch (propType) {
  115
+                        case "boolean":
  116
+                            value = affectedWidget.attr('checked')?true:false;
  117
+                            break;
  118
+                        case "record-array":
  119
+                            value = event.oldValue; // FIXME: oldValue can't passed here.
  120
+                            break;
  121
+                        default:
  122
+                            value = affectedWidget.val();
  123
+                            break;
108 124
                     }
109  
-                    if(event.newValue != value) {
110  
-                        affectedWidget[0].scrollIntoViewIfNeeded();
111  
-                        if(typeof(event.newValue) === 'boolean') {
112  
-                            affectedWidget.effect('pulsate', { times:3 }, 200);
113  
-                        } else {
114  
-                            affectedWidget.effect('highlight', {}, 1000);
115  
-                        }
116  
-                        widget._setProperty(event.property, event.newValue);
  125
+
  126
+                    // Compare the newValue is equal with value, then return directly.
  127
+                    if (event.newValue == value)
  128
+                        return
  129
+
  130
+                    // Update ADM and apply effects.
  131
+                    switch (propType) {
  132
+                        case "boolean":
  133
+                            if (affectedWidget) {
  134
+                                affectedWidget[0].scrollIntoViewIfNeeded();
  135
+                                affectedWidget.effect('pulsate', { times:3 }, 200);
  136
+                            }
  137
+                            widget._setProperty(event.property, propType, event.newValue);
  138
+                            break;
  139
+                        case "record-array":
  140
+                            value = event.oldValue;
  141
+                            // TODO: Do something with affectedWidget
  142
+                            // affectedWidget = event.element;
  143
+                            widget._redrawProperty(
  144
+                                event.property,
  145
+                                widget._generateRecordArraryTable(widget, event.node, event.property)
  146
+                            );
  147
+                            break;
  148
+                        default:
  149
+                            if (affectedWidget) {
  150
+                                affectedWidget[0].scrollIntoViewIfNeeded();
  151
+                                affectedWidget.effect('highlight', {}, 1000);
  152
+                            }
  153
+                            widget._setProperty(event.property, propType, event.newValue);
  154
+                            break;
117 155
                     }
118 156
                     return;
119 157
                 } else if (event.property !== 'css') {
@@ -138,6 +176,183 @@
138 176
             return;
139 177
         },
140 178
 
  179
+        _generateSelectMenuOption: function(node, property, child, index, props) {
  180
+            var changeCallback = function(event) {
  181
+                var newValue, self = $(this);
  182
+                props[property].children[index][event.data.key] = self.val();
  183
+                newValue = props[property];
  184
+                node.fireEvent("modelUpdated", {
  185
+                    type: "propertyChanged",
  186
+                    node: node,
  187
+                    property: property,
  188
+                    element: self,
  189
+                    newValue: newValue,
  190
+                    index: index
  191
+                });
  192
+            };
  193
+
  194
+            if (!props)
  195
+                props = node.getProperties();
  196
+            return $('<tr/>').data('index', index)
  197
+                .addClass("options")
  198
+                .append('<td/>')
  199
+                    .children().eq(0)
  200
+                    .append('<img/>')
  201
+                    .children(':first')
  202
+                    .attr('src', "src/css/images/propertiesDragIconSmall.png")
  203
+                    .end()
  204
+                    .end().end()
  205
+                .append('<td/>')
  206
+                    .children().eq(1)
  207
+                    .append('<input type="text"/>')
  208
+                        .children().eq(0)
  209
+                        .val(child.text)
  210
+                        .addClass('title optionInput')
  211
+                        .change({key: 'text'}, changeCallback)
  212
+                        .end().end()
  213
+                    .end().end()
  214
+                .append('<td/>')
  215
+                    .children().eq(2)
  216
+                    .append('<input type="text"/>')
  217
+                        .children().eq(0)
  218
+                        .val(child.value)
  219
+                        .addClass('title optionInput')
  220
+                        .change({key: 'value'}, changeCallback)
  221
+                        .end().end()
  222
+                    .end().end()
  223
+                .append('<td/>')
  224
+                    .children().eq(3)
  225
+                    .append('<div class="delete button">Delete</div>')
  226
+                        .children(':first')
  227
+                        // add delete option handler
  228
+                        .click(function(e) {
  229
+                            try {
  230
+                                var newValue, self = $(this);
  231
+                                // Generate ADM properties
  232
+                                index = self.parent().parent().data('index');
  233
+                                props[property].children.splice(index, 1);
  234
+                                // Instead by draw, so comment following lines.
  235
+                                /*
  236
+                                // Remove the row element after clicked delete button
  237
+                                self.parent().parent().remove();
  238
+                                */
  239
+                                newValue = props[property];
  240
+                                // Trigger the modelUpdated event.
  241
+                                node.fireEvent("modelUpdated", {
  242
+                                    type: "propertyChanged",
  243
+                                    node: node,
  244
+                                    property: property,
  245
+                                    element: self,
  246
+                                    newValue: newValue,
  247
+                                    index: index
  248
+                                });
  249
+                            }
  250
+                            catch (err) {
  251
+                                console.error(err.message);
  252
+                            }
  253
+                            e.stopPropagation();
  254
+                            return false;
  255
+                        })
  256
+                        .end()
  257
+                    .end().end();
  258
+        },
  259
+
  260
+        _generateRecordArraryTable: function(widget, node, property, props) {
  261
+            var child, table = $('<table/>')
  262
+                .attr('id', property + '-value')
  263
+                .addClass('selectTable')
  264
+                .attr('cellspacing', '5');
  265
+
  266
+            if (!props)
  267
+                props = node.getProperties();
  268
+
  269
+            $('<tr/>')
  270
+                .append('<td width="5%"></td>')
  271
+                .append('<td width="45%"> Text </td>')
  272
+                    .children().eq(1)
  273
+                    .addClass('title')
  274
+                    .end().end()
  275
+                .append('<td width="45%"> Value </td>')
  276
+                    .children().eq(2)
  277
+                    .addClass('title')
  278
+                    .end().end()
  279
+                .append('<td width="5%"></td>')
  280
+                .appendTo(table);
  281
+            for (var i = 0; i< props[property].children.length; i++){
  282
+                child = props[property].children[i];
  283
+                table.append(
  284
+                    this._generateSelectMenuOption(node, property, child, i, props)
  285
+                );
  286
+            }
  287
+
  288
+            // add add items handler
  289
+            $('<tr><td colspan="3">+ add item</td></tr>')
  290
+                .children(':first')
  291
+                .addClass('rightLabel title')
  292
+                .attr('id', 'addOptionItem')
  293
+                .end()
  294
+                .click(function(e) {
  295
+                    var newValue, self = $(this);
  296
+                    try {
  297
+                        var rowElement, index = props[property].children.length,
  298
+                            optionItem = {
  299
+                                'text': 'Option',
  300
+                                'value': 'Value'
  301
+                            };
  302
+                        props[property].children.push(optionItem);
  303
+                        // Instead by draw, so comment following lines.
  304
+                        /*
  305
+                        rowElement = widget._generateSelectMenuOption(
  306
+                            node, property, optionItem, index, props
  307
+                        );
  308
+                        */
  309
+                        table.append(rowElement);
  310
+                        $(this).insertAfter(rowElement);
  311
+                        newValue = props[property];
  312
+                        node.fireEvent("modelUpdated", {
  313
+                             type: "propertyChanged",
  314
+                             node: node,
  315
+                             property: property,
  316
+                             element: self,
  317
+                             newValue: newValue,
  318
+                             index: index
  319
+                         });
  320
+                    } catch (err) {
  321
+                        console.error(err.message);
  322
+                    }
  323
+                    e.stopPropagation();
  324
+                    return false;
  325
+                })
  326
+                .appendTo(table);
  327
+
  328
+            // make option sortable
  329
+            table.sortable({
  330
+                axis: 'y',
  331
+                items: '.options',
  332
+                containment: table.find('tbody'),
  333
+                start: function(event, ui) {
  334
+                    widget.origRowIndex = ui.item.index() - 1;
  335
+                },
  336
+                stop: function(event, ui) {
  337
+                    var optionItem, curIndex = ui.item.index() - 1,
  338
+                        origIndex = widget.origRowIndex;
  339
+                        optionItem = props[property].children.splice(origIndex,1)[0];
  340
+
  341
+                    props[property].children.splice(curIndex, 0, optionItem);
  342
+                    node.fireEvent("modelUpdated", {
  343
+                        type: "propertyChanged",
  344
+                        node: node,
  345
+                        property: property,
  346
+                        element: table,
  347
+                        newValue: props[property],
  348
+                        index: ui.item.index()
  349
+                    });
  350
+                }
  351
+            });
  352
+
  353
+            return table;
  354
+        },
  355
+
141 356
         _showProperties: function(node) {
142 357
             var labelId, labelVal, valueId, valueVal, count,
143 358
                 widget = this, type,  i, child, index, propType,
@@ -251,137 +466,7 @@
251 466
                         break;
252 467
 
253 468
                     case "record-array":
254  
-                        $('<table/>')
255  
-                            .attr('id', 'selectOption')
256  
-                            .attr('cellspacing', '5')
257  
-                            .appendTo(value);
258  
-                        var selectOption = value.find('#selectOption');
259  
-                        $('<tr/>')
260  
-                            .append('<td width="5%"></td>')
261  
-                            .append('<td width="45%"> Text </td>')
262  
-                                .children().eq(1)
263  
-                                .addClass('title')
264  
-                                .end().end()
265  
-                            .append('<td width="45%"> Value </td>')
266  
-                                .children().eq(2)
267  
-                                .addClass('title')
268  
-                                .end().end()
269  
-                            .append('<td width="5%"></td>')
270  
-                            .appendTo(selectOption);
271  
-                        for (i = 0; i< props[p].children.length; i ++){
272  
-                            child = props[p].children[i];
273  
-                            $('<tr/>').data('index', i)
274  
-                                .addClass("options")
275  
-                                .append('<td/>')
276  
-                                    .children().eq(0)
277  
-                                    .append('<img/>')
278  
-                                    .children(':first')
279  
-                                    .attr('src', "src/css/images/propertiesDragIconSmall.png")
280  
-                                    .end()
281  
-                                    .end().end()
282  
-                                .append('<td/>')
283  
-                                    .children().eq(1)
284  
-                                    .append('<input type="text"/>')
285  
-                                        .children().eq(0)
286  
-                                        .val(child.text)
287  
-                                        .addClass('title optionInput')
288  
-                                        .change(node, function (event) {
289  
-                                            index = $(this).parent().parent().data('index');
290  
-                                            props['options'].children[index].text = $(this).val();
291  
-                                            node.fireEvent("modelUpdated",
292  
-                                                {type: "propertyChanged",
293  
-                                                 node: node,
294  
-                                                 property: 'options'});
295  
-                                        })
296  
-                                        .end().end()
297  
-                                    .end().end()
298  
-                                .append('<td/>')
299  
-                                    .children().eq(2)
300  
-                                    .append('<input type="text"/>')
301  
-                                        .children().eq(0)
302  
-                                        .val(child.value)
303  
-                                        .addClass('title optionInput')
304  
-                                        .change(node, function (event) {
305  
-                                            index = $(this).parent().parent().data('index');
306  
-                                            props['options'].children[index].value = $(this).val();
307  
-                                            node.fireEvent("modelUpdated",
308  
-                                                {type: "propertyChanged",
309  
-                                                 node: node,
310  
-                                                 property: 'options'});
311  
-                                        })
312  
-                                        .end().end()
313  
-                                    .end().end()
314  
-                                .append('<td/>')
315  
-                                    .children().eq(3)
316  
-                                    .append('<div class="delete button">Delete</div>')
317  
-                                        .children(':first')
318  
-                                        // add delete option handler
319  
-                                        .click(function(e) {
320  
-                                            try {
321  
-                                                index = $(this).parent().parent().data('index');
322  
-                                                props['options'].children.splice(index, 1);
323  
-                                                node.fireEvent("modelUpdated",
324  
-                                                    {type: "propertyChanged",
325  
-                                                        node: node,
326  
-                                                    property: 'options'});
327  
-                                            }
328  
-                                            catch (err) {
329  
-                                                console.error(err.message);
330  
-                                            }
331  
-                                            e.stopPropagation();
332  
-                                            return false;
333  
-                                        })
334  
-                                        .end()
335  
-                                    .end().end()
336  
-                               .appendTo(selectOption);
337  
-                        }
338  
-
339  
-                        // add add items handler
340  
-                        $('<label for=items><u>+ add item</u></label>')
341  
-                            .children(':first')
342  
-                            .addClass('rightLabel title')
343  
-                            .attr('id', 'addOptionItem')
344  
-                            .end()
345  
-                            .appendTo(value);
346  
-                        value.find('#addOptionItem')
347  
-                            .click(function(e) {
348  
-                                try {
349  
-                                    var optionItem = {};
350  
-                                    optionItem.text = "Option";
351  
-                                    optionItem.value = "Value";
352  
-                                    props['options'].children.push(optionItem);
353  
-                                    node.fireEvent("modelUpdated",
354  
-                                                  {type: "propertyChanged",
355  
-                                                   node: node,
356  
-                                                   property: 'options'});
357  
-                                }
358  
-                                catch (err) {
359  
-                                    console.error(err.message);
360  
-                                }
361  
-                                e.stopPropagation();
362  
-                                return false;
363  
-                            });
364  
-
365  
-                        // make option sortable
366  
-                        value.find('#selectOption tbody').sortable({
367  
-                            axis: 'y',
368  
-                            items: '.options',
369  
-                            containment: value.find('#selectOption tbody'),
370  
-                            start: function(event, ui) {
371  
-                                widget.origRowIndex = ui.item.index() - 1;
372  
-                            },
373  
-                            stop: function(event, ui) {
374  
-                                var optionItem, curIndex = ui.item.index() - 1,
375  
-                                    origIndex = widget.origRowIndex;
376  
-                                    optionItem = props['options'].children.splice(origIndex,1)[0];
377  
-
378  
-                                props['options'].children.splice(curIndex, 0, optionItem);
379  
-                                node.fireEvent("modelUpdated",
380  
-                                              {type: "propertyChanged",
381  
-                                               node: node,
382  
-                                               property: 'options'});
383  
-                            }
384  
-                        });
  469
+                        value.append(this._generateRecordArraryTable(widget, node, p, props));
385 470
                         break;
386 471
                     case "targetlist":
387 472
                         container = node.getParent();
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.