test u
test u

Reputation: 37

Dynamically grouping html elements in side of a parent div class

I would like to sort each "panel" into one div each depending on what class my element has, any help would be greatly appreciated.

I've gotten to the point of where I'm dynamically setting the class tag for each panel, but I can't figure out how to group them into one div per dynamic class that I set based off my json array element "PressNo".

JS

//this is where I set the panel data

function Panel(opts) {
  
  return ['<div class="', opts.classcontrol, '">',
          '<div class="panel">',
          '  <div class="panel-heading">',
          '    <h4>',
          '     <span class="status"><b class="fa fa-', opts.icon, '"></b></span>',
          '     <span class="name">', Utils.escapeHtml(opts.title), '</span>',
          '    </h4>',
          '  </div>',
          '  <div class="panel-body">',
          (opts.trustedBody || Utils.escapeHtml(opts.body)),
          '  </div>',
          '</div></div>'].join('');

}

// get json data for panel 

function ConfigurationController(element) {
  if ( !element ) { throw new Error('Cannot create ConfigurationController: Element Required');}
  var self = this,
    _limit = 2,
    apiUrl = "http://localhost:58938/api/ShopViewDisplay/PLTO/PLTO/10";

  // Expose Public method(s)
  this.load = load;
  //this.render = render;

  function load() {
    reset()
    $.ajax({

        url : apiUrl,
        type : 'GET',
        dataType:'json',
        success : function(data) {              
                    data.map(renderItem, function(el) {
                    element.append(el);
        });
        },  
        error : function(request,error)
        {
            alert("Request: "+JSON.stringify(request));
        }
    });
  }
  
  // this renders each item 

  function renderItem(obj, index, list) {
    var callback = typeof this === 'function' ? this : false;
    // This could use document create fragment, possible speed boost
    // 20% of the time, pick random status icon, in all other cases pick the 'good' check icon.
    
                function renderItem(obj) {
                    var callback = typeof this === 'function' ? this : false;
        
                    var statusIcon = "fire";
                    var itemPanel = Panel({
                        icon: statusIcon,
                        title: obj.WorkOrderNumber,
                        classcontrol: obj.PressNo,
                        trustedBody: [
                            '    <div class="PressNo"><b></b> Machine:  <br>', Utils.escapeHtml(obj.PressNo), '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="Priority"><b></b> Priority:  <br>', Utils.escapeHtml(obj.Priority),
                            '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="PartNo"><b></b> Part:  <br>', Utils.escapeHtml(obj.Part), '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="Material"><b></b> Material: <br>', Utils.escapeHtml(obj.PartDesc), '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="Setup"><b></b> Setup(E/A): <br>',
                            Utils.escapeHtml(obj.EstActSetupHrs).replace('\r\n', ' / '), '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="Run"><b></b> Run (E/A): <br>',
                            Utils.escapeHtml(obj.EstActRunHrs).replace('\r\n', ' / '), '</br></div>',
                            '    <br>                                                                   ',
                            '    <div class="Qty"><b></b> Qty: <br>',
                            Utils.escapeHtml(obj.CalEndCompleteQty).replace('\r\n', ' / '), ' </br></div>'
                        ].join('\n')
                    });
    
                    itemPanel = $(itemPanel);
    
        myFunction();

    return (typeof(callback) === 'function' ? callback(itemPanel) : itemPanel);}

HTML

Here is where I append the panels

<body>
<div id="configurationList">
    <h2>
        <b class="fa fa-refresh fa-spin"></b>
        <i>Loading, please wait...</i>
    </h2>
</div>
</body>

Example of what I would like to see happen:

 <div class="5-1">
    panel 1 - class="panel" - I have PressNo 5-1
    panel 6 - class="panel" - I have PressNo 5-1
 </div>

 <div class="7">
    panel 2 - class="panel" - I have PressNo 7
    panel 8 - class="panel" - I have PressNo 7
 </div>

 <div class="9-3">
    panel 9 - class="panel" - I have PressNo 9-3
    panel 10 - class="panel" - I have PressNo 9-3
 </div>

This is what it looks like now

This is what I would like it to look like

update trying @obscure suggestion/answer

I get the following in my browser console -

TypeError: theDiv[0] is undefined

When I console log I get the following output (it looks like my data hasn't been loaded yet).

console.log(id, document.getElementsByClassName(id));
1 HTMLCollection { length: 0 } index:116:25

Full code

@{
    Layout = "";
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <link href="http://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet" type="text/css">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        'use strict';

        var Utils = {
            escapeHtml: function _escapeHtml(s) { // Prevent code injection and rendering issues
                return String(s).replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;');
            }
        };

        function Panel(opts) {

            /*return ['<div class="', opts.classcontrol, '">',
                    '<div class="panel">',
                    '  <div class="panel-heading">',
                    '    <h4>',
                    '     <span class="status"><b class="fa fa-', opts.icon, '"></b></span>',
                    '     <span class="name">', Utils.escapeHtml(opts.title), '</span>',
                    '    </h4>',
                    '  </div>',
                    '  <div class="panel-body">',
                    (opts.trustedBody || Utils.escapeHtml(opts.body)),
                    '  </div>',
                    '</div></div>'].join('');
              */
            return ['<div class="', opts.classcontrol, '">',
                '<div class="panel">',
                '  <div class="panel-heading">',
                '    <h4>',
                '     <span class="status"><b class="fa fa-', opts.icon, '"></b></span>',
                '     <span class="name">', Utils.escapeHtml(opts.title), '</span>',
                '    </h4>',
                '  </div>',
                '  <div class="panel-body">',
                (opts.trustedBody || Utils.escapeHtml(opts.body)),
                '  </div>',
                '</div></div>'].join('');
        }

        function ConfigurationController(element) {
            if (!element) {
                throw new Error('Cannot create ConfigurationController: Element Required');
            }
            var self = this,
                apiUrl = "http://pdapi.pennunited.com/api/ShopViewDisplay/" + "@ViewBag.pathProc";
            console.log(apiUrl);

            // Expose Public method(s)
            this.load = load;
            //this.render = render;

            function load() {
                // Attempt ajax call; on fail: use dummy data
                reset();
                $.ajax({
                    url: apiUrl,
                    type: 'GET',
                    dataType: 'json',
                    success: function(data) {
                        data.map(renderItem,
                            function(el) {
                                element.append(el);
                                
                            });
                    },
                    error: function(request, error) {
                        alert("Request: " + JSON.stringify(request) + " Error: " + error);
                    }
                });
            }

            function reset() {
                element.children().remove();
                return element;
            }

            function renderItem(obj) {
                var callback = typeof this === 'function' ? this : false;
    
                var statusIcon = "fire";
                var itemPanel = Panel({
                    icon: statusIcon,
                    title: obj.WorkOrderNumber,
                    classcontrol: obj.PressNo,
                    trustedBody: [
                        '    <div class="PressNo"><b></b> Machine:  <br>', Utils.escapeHtml(obj.PressNo), '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="Priority"><b></b> Priority:  <br>', Utils.escapeHtml(obj.Priority),
                        '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="PartNo"><b></b> Part:  <br>', Utils.escapeHtml(obj.Part), '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="Material"><b></b> Material: <br>', Utils.escapeHtml(obj.PartDesc), '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="Setup"><b></b> Setup(E/A): <br>',
                        Utils.escapeHtml(obj.EstActSetupHrs).replace('\r\n', ' / '), '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="Run"><b></b> Run (E/A): <br>',
                        Utils.escapeHtml(obj.EstActRunHrs).replace('\r\n', ' / '), '</br></div>',
                        '    <br>                                                                   ',
                        '    <div class="Qty"><b></b> Qty: <br>',
                        Utils.escapeHtml(obj.CalEndCompleteQty).replace('\r\n', ' / '), ' </br></div>'
                    ].join('\n')
                });

                itemPanel = $(itemPanel);

                var id = Utils.escapeHtml(obj.PressNo);
                console.log(id, document.getElementsByClassName(id));
                var theDiv=document.getElementsByClassName(id);
                theDiv[0].appendChild(itemPanel);


                //myFunction();

                return (typeof (callback) === 'function' ? callback(itemPanel) : itemPanel);
            }
        }

        function scroll(speed) {
            $('html, body').animate({ scrollTop: $(document).height() - $(window).height() }, speed, function() {
                $(this).animate({ scrollTop: 0 }, speed);
            });

        }


        $(document).ready(function _onLoad() {
            var ctrl = new ConfigurationController($('#configurationList'));
            ctrl.load();

            //ctrl.load();
            //var speed = 15000;
            //scroll(speed)
            //setInterval(function () { scroll(speed) }, speed * 8);
            //setInterval(ctrl.load(), 900000);
        });


    </script>
    <style>
        body {
            background-color: black;
            font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
            margin: 0px;
            padding: 82px 0px 0px 0px;
            /* for fixed heading */
            /*padding-top: 67px;*/
        }


        h1 { margin: 4px 2px; }

        h4 { margin: 2px 2px; }

        .page-header-fixed {
            left: 0;
            position: fixed;
            right: 0;
            top: 0px;
        }

        /* Define a bootstrap-ish minimal style
        ---- 425363 */

        .text-success { color: #94c0e9; }

        .text-info { color: #0071ce; }

        .text-warning { color: #ff8300; }

        .PressNo { color: green; }

        .Priority { color: red; }

        .page-header {
            background: #425363;
            box-shadow: rgba(0, 0, 0, 0.90) 5px 1px 4px 0px;
            color: #FFF;
            margin-bottom: 10px;
            padding: 6px 10px;
            /*line-height: 48px;*/
            transition: all 0.2s;
        }

        .panel {
            background-color: #FFF;
            border: 1px solid #DEDEDE;
            border-radius: 2px 2px 2px 2px;
            border-top: none;
            box-sizing: border-box;
            color: #666666;
            font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
            font-size: 15px;
            line-height: 20px;
            margin: 8px 2px;
            transition: all 0.25s ease-in;
        }

        .panel-heading {
            background-color: #0071ce;
            border-color: #2196F3;
            box-sizing: border-box;
            color: #fff;
            cursor: pointer;
            display: block;
            font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
            font-size: 18px;
            font-weight: 400;
            line-height: 19px;
            padding: 10px 15px 10px 15px;
            transition: background-color 0.25s ease-in, color 0.25s ease-in;
        }

        .panel-body {
            padding: 15px;
            transition: background-color 0.25s ease-in, color 0.25s ease-in;
        }

        /*.btn {
          border: none;
          font-family: inherit;
          cursor: pointer;
          padding: 25px 80px;
          display: inline-block;
          margin: 15px 30px;
          text-transform: uppercase;
          letter-spacing: 1px;
          font-weight: 700;
          outline: none;
          position: relative;
        }*/

        .status .fa {
            font-size: 22px;
            margin: 6px;
        }

        .panel-footer {
            text-align: right;
            width: 100%;
        }

        .panel-footer .fa {
            cursor: pointer;
            font-size: 18px;
            margin: 8px;
        }

        .panel .fa { opacity: 1; }

        .panel:hover .panel-heading { background-color: #ff8300; }

        .panel:hover { box-shadow: 2px 2px 3px 3px rgba(102, 102, 102, 0.8); }

        .panel:hover .fa {
            color: #ff8300;
            text-shadow: 2px 2px 0px #FFFFFF;
            transition: all 0.2s ease, font-size 0.2s ease-in;
        }

        .panel:hover .panel-heading .fa { color: #333333; }

        .panel-heading .fa-exclamation-circle { color: yellow; }

        .panel-heading .fa-check { color: #FFF; }

        .panel-heading .fa-fire {
            color: #ff8300;
            font-size: 26px;
        }

        .panel-body b.fa {
            font-size: 20px;
            text-align: center;
            width: 30px;
        }


        #configurationList {
            -webkit-flex-flow: row wrap;
            display: flex;
            flex-flow: row wrap;
            justify-content: space-around;
            width: 99%;
        }

        #configurationList .panel {
            display: inline-block;
            min-height: 100px;
            width: 250px;
        }
    </style>
</head>
<body>
<div id="configurationList">
    <h2>
        <b class="fa fa-refresh fa-spin"></b>
        <i>Loading, please wait...</i>
    </h2>
</div>
</body>
</html>

Upvotes: 3

Views: 601

Answers (1)

obscure
obscure

Reputation: 12891

At the moment you're generating each container DIV - e.g. class="5.1" with each panel.

function Panel(opts) {

  return ['<div class="', opts.classcontrol, '">',
          '<div class="panel">',
          '  <div class="panel-heading">',
          '    <h4>',
          '     <span class="status"><b class="fa fa-', opts.icon, '"></b></span>',
          '     <span class="name">', Utils.escapeHtml(opts.title), '</span>',
          '    </h4>',
          '  </div>',
          '  <div class="panel-body">',
          (opts.trustedBody || Utils.escapeHtml(opts.body)),
          '  </div>',
          '</div></div>'].join('');

}

I assume '<div class="', opts.classcontrol, '">' is the target div. Anyway, this means you're generating a new container div each time you generate a new panel. You should make sure that there isn't a div that uses that specific class before you create a new one.

function Panel(opts) {
  var theDiv = document.getElementsByClassName(opts.classcontrol);
  var theArray = ['<div class="panel">',
    '  <div class="panel-heading">',
    '    <h4>',
    '     <span class="status"><b class="fa fa-', opts.icon, '"></b></span>',
    '     <span class="name">', Utils.escapeHtml(opts.title), '</span>',
    '    </h4>',
    '  </div>',
    '  <div class="panel-body">',
    (opts.trustedBody || Utils.escapeHtml(opts.body)),
    '  </div>',
    '</div></div>'
  ];
  if (theDiv.length == 0) {
    theArray.splice(0, 0, '<div class="', opts.classcontrol, '">');
    theArray.push("</div>");
  }

  return theArray.join('');
}

Inside the function renderItem() we need to make this distinction once more.

Right after

itemPanel = $(itemPanel);

Insert this

var theDiv = document.getElementsByClassName(obj.PressNo);
if (theDiv.length == 0) {
  return (typeof(callback) === 'function' ? callback(itemPanel) : itemPanel);
} else {
  theDiv[0].appendChild(itemPanel);
  return undefined;
}

and remove

return (typeof(callback) === 'function' ? callback(itemPanel) : itemPanel);

at the end of that function.

This appends the newly created panel to the corresponding parent div - in case it exists. The return undefined is a workaround for this code inside your load() function

function(el) {
  element.append(el);

});

it would try to append whatever el is to element. Since we might already appended the panel before we need to make sure it won't get appended a second time. So modify the above to

function(el) {
  if (el != undefined) {
    element.append(el);
  }
});

Upvotes: 1

Related Questions